9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MutableStateの3通りの宣言方法とその使い分けを考える

Last updated at Posted at 2021-12-11

Jetpack ComposeのComposable内でMutableStateを宣言する場合、大きく3通りの記述方法があります。

val mutableState = remember { mutableStateOf(default) }
var value by remember { mutableStateOf(default) }
val (value, setValue) = remember { mutableStateOf(default) }

公式ドキュメントによれば「機能は同じだから状況に応じて読みやすいものを使ってね」とのことですが、実際のところ、どう使い分けるべきでしょうか?

結論

  • 基本的にはdelegated propertiesを使うのが良さそう
    • var value by remember { mutableStateOf(default) }
  • state hoisting等でsetterを引数に渡したいときはdestructuring declarationsを使う
    • val (value, setValue) = remember { mutableStateOf(default) }

考察

まず、用途が似ているのは次の2つだと思います。

val mutableState = remember { mutableStateOf(default) }
var value by remember { mutableStateOf(default) }

記法としては前者が.valueによってアクセスする一方、後者はシンプルです。

// Read
println(mutableState.value)
println(value)

// Mutation
mutableState.value = someValue
value = someValue

従って、基本的にはdelegated propertiesを使うのが良いでしょう。
Composeの公式サンプルでも基本的にはdelegated propertiesを使用しているようです。

前者はいつ使うのか?という話ですが、valueではなくオブジェクトそのもの(State/MutableState)にアクセスしたい場合には前者の記法になりそうです。

次にsetValueを同時に宣言するパターンです。

val (value, setValue) = remember { mutableStateOf(default) }

明らかな違いはsetValueが変数として宣言されている点です。
これは他のComposableに実引数として渡すときに便利です。

val (value, onValueChanged) = remember { mutableStateOf(default) }
SomeComposable(value, onValueChanged)

これはstate hoistingの際に使うことが多そうです。公式サンプルでもそういったユースケースで使われています。

その他: なぜ3通りの書き方で動くのか?

var value by remember { mutableStateOf(default) }
はKotlinのdelegated propertiesによって実現されています。

内部的にはState<T>.getValueMutableState<T>.setValueを実行しています。従って次のimport文が必要になるわけですね。

import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue

そして、
val (value, setValue) = remember { mutableStateOf(default) }
はKotlinのdestructuring declarationsによって実現されています。

実際にMutableStateの定義を確認すると、component1及びcomponent2が確認できると思います。

@Stable
interface MutableState<T> : State<T> {
    override var value: T
    operator fun component1(): T
    operator fun component2(): (T) -> Unit
}
9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?