Jetpack Compose State:修改类属性 [英] Jetpack Compose State: Modify class property

查看:38
本文介绍了Jetpack Compose State:修改类属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下两个示例仅将‘a’添加到给定默认值。使用的compose_version1.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'")
        }
    }
}

然而,这并不总是实用的。例如,数据比单个字段更复杂。例如一个类,甚至一个Roomdata 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不行。这是我的一个简单错误,还是我错过了应该如何修改这个类实例的大局?

编辑:

我找到了一种某种方法来实现此功能,但似乎效率不高。但是,它确实与Reaction管理状态的方式一致,因此这可能是正确的做法。

示例2中的问题非常清楚,myNextThing不是原始myThing的副本,而是对它的引用。就像Reaction一样,Jetpack Compose在修改状态时似乎需要一个全新的对象。这可以通过以下两种方式之一完成:

  1. 创建MyThing类的新实例,更改需要更改的内容,然后使用新的类实例调用setMyThing()
  2. class MyThing更改为data class MyThing,并使用copy()函数创建具有相同属性的新实例。然后,更改所需的属性并调用setMyThing()。在我的问题上下文中,这是最好的方法,因为我明确表示,我希望使用此方法修改Android Room使用的给定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'")
        }
    }
}

推荐答案

确实,在我看来最好的方法是复制()一个数据类。

在使用自定义data classremember()的特定情况下,这可能确实是最好的选择,不过通过在copy()函数上使用命名参数可以更简洁地完成此操作:

// the class to be modified
data class MyThing(var name: String = "Ma", var age: Int = 0)

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

  Column {
    Text(text = myThing.name)
    // button to add "a" to the end of the name
    Button(onClick = { myThingSetter(myThing.copy(name = myThing.name + "a")) }) {
      Text(text = "Add an 'a'")
    }
    // button to increment the new "age" field by 1
    Button(onClick = { myThingSetter(myThing.copy(age = myThing.age + 1)) }) {
      Text(text = "Increment age")
    }
  }
}
但是,我们仍将更新视图模型并观察它们的结果(LiveDataStateFlow、RxJavaObservable等)。我希望remember { mutableStateOf() }将在本地用于尚未准备好提交到视图模型但需要多位用户输入的数据,因此需要将其表示为状态。您是否觉得需要data class由您决定。

这是我的一个简单错误,还是我错过了应该如何修改此类实例的大问题?

Compose无法知道对象已更改,因此它不知道需要重新组合。

总体而言,Compose是围绕对不可变数据流的反应而设计的。remember { mutableStateOf() }创建本地流。

不过,我们非常欢迎另一种方法。

您不限于单个remember

@Composable
fun MyScreen() {
  val name = remember { mutableStateOf("Ma") }
  val age = remember { mutableStateOf(0) }

  Column {
    Text(text = name.value)
    // button to add "a" to the end of the name
    Button(onClick = { name.value = name.value + "a"}) {
      Text(text = "Add an 'a'")
    }
    // button to increment the new "age" field by 1
    Button(onClick = { age.value = age.value + 1 }) {
      Text(text = "Increment age")
    }
  }
}

这篇关于Jetpack Compose State:修改类属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆