Jetpack Compose 状態: クラス プロパティを変更する 質問する

Jetpack Compose 状態: クラス プロパティを変更する 質問する

以下の 2 つの例では、指定されたデフォルト値に単に 'a' を追加します。compose_version使用されているのは、1.0.0-alpha03今日の時点で最新のものです (私の知る限り)。

この例は、私が調査中に見つけたほとんどの例と最も似ています。

例1

@Composable
fun MyScreen() {
    val (name, setName) = remember { mutableStateOf("Ma") }

    Column {
        Text(text = name) // 'Ma'
        Button(onClick = {
                setName(name + "a") // change it to 'Maa'
        }) {
            Text(text = "Add an 'a'")
        }
    }
}

ただし、これは必ずしも実用的ではありません。たとえば、データが単一のフィールドよりも複雑だったとします。たとえば、クラスやRoom data class

例2

// the class to be modified
class MyThing(var name: String = "Ma");


@Composable
fun MyScreen() {
    val (myThing, setMyThing) = remember { mutableStateOf(MyThing()) }

    Column {
        Text(text = myThing.name) // 'Ma'
        Button(onClick = {
                var nextMyThing = myThing
                nextMyThing.name += "a" // change it to 'Maa'
                setMyThing(nextMyThing)
        }) {
            Text(text = "Add an 'a'")
        }
    }
}

もちろん、例1動作しますが、例2違います。これは私の単純な間違いでしょうか、それともこのクラス インスタンスをどのように変更すればよいかという全体像を見落としているのでしょうか。

編集:

私は持っているちょっとこれを機能させる方法を見つけましたが、非効率的であるようです。ただし、これは React が状態を管理する方法と一致しているため、正しい方法である可能性があります。

問題は例2明らかに、これはmyNextThing元の のコピーではなくmyThing、むしろ元の への参照です。React と同様に、Jetpack Compose は状態を変更するときに完全に新しいオブジェクトを必要とするようです。これは、次の 2 つの方法のいずれかで実行できます。

  1. クラスの新しいインスタンスを作成しMyThing、変更が必要な部分を変更し、setMyThing()新しいクラスのインスタンスで呼び出す
  2. class MyThingに変更しdata class MyThingcopy()関数を使用して、同じプロパティを持つ新しいインスタンスを作成します。次に、目的のプロパティを変更して を呼び出します。Android Room で使用されるsetMyThing()特定の のデータを変更するためにこれを使用したいと明示的に述べたので、これは私の質問のコンテキストでは最善の方法です。data class

例3 (機能的)

// the class to be modified
data class MyThing(var name: String = "Ma");


@Composable
fun MyScreen() {
    val (myThing, setMyThing) = remember { mutableStateOf(MyThing()) }

    Column {
        Text(text = myThing.name) // 'Ma'
        Button(onClick = {
                var nextMyThing = myThing.copy() // make a copy instead of a reference
                nextMyThing.name += "a" // change it to 'Maa'
                setMyThing(nextMyThing)
        }) {
            Text(text = "Add an 'a'")
        }
    }
}

ベストアンサー1

さて、これについて疑問に思っている人のために、この問題を解決するより簡単な方法があります。次のように可変状態プロパティを定義します。

//There is a second paremeter wich defines the policy of the changes on de state if you
//set this value to neverEqualPolicy() you can make changes and then just set the value
class Vm : ViewModel() {
 val dummy = mutableStateOf(value = Dummy(), policy= neverEqualPolicy())

 //Update the value like this 
 fun update(){
 dummy.value.property = "New value"
//Here is the key since it has the never equal policy it will treat them as different no matter the changes
 dummy.value = dummy.value
 }
}

利用可能なポリシーの詳細については、以下をご覧ください。スナップショットミューテーションポリシー

おすすめ記事