【发布时间】:2020-09-23 12:46:27
【问题描述】:
使用EditText 修改简单值和data classes 相当简单,通常如下所示:
data class Person(var firstName: String, var lastName: Int)
// ...
val (person, setPerson) = remember { mutableStateOf(Person()) }
// common `onChange` function handles both class properties, ensuring maximum code re-use
fun <T> onChange(field: KMutableProperty1<Person, T>, value: T) {
val nextPerson = person.copy()
field.set(nextPerson, value)
setPerson(nextPerson)
}
// text field for first name
TextField(
value = person.firstName,
onChange = { it -> onChange(Person::firstName, it) })
// text field for last name name
TextField(
value = person.lastName,
onChange = { it -> onChange(Person::lastName, it) })
如您所见,此示例中的代码具有高度可重用性:感谢 Kotlin 的反射功能,我们可以使用单个 onChange 函数来修改此类中的每个属性。
但是,当Person 类不是从头开始实例化,而是通过Room 从磁盘中提取时,就会出现问题。例如,PersonDao 可能包含一个 `findOne() 函数,如下所示:
@Query("SELECT * FROM peopleTable WHERE id=:personId LIMIT 1")
fun findOne(personId: String): LiveData<Person>
但是,由于多种原因,您不能真正在 remember {} 中使用此 LiveData:
- 虽然
LiveData有一个名为observeAsState()的函数,但它返回State<T>而不是MutableState<T>,这意味着您不能使用TextFields对其进行修改。因此,这不起作用:remember { personFromDb.observeAsState()}
- 你不能
.copy()你从你的数据库中得到Person,因为你的组件将在返回房间查询之前呈现,这意味着你不能这样做,因为Person类实例将被记住为@987654339 @:remember { mutableStateOf(findPersonQueryResult.value) }
鉴于此,处理此问题的正确方法是什么?是否应该将包含TextFields 的组件包装在另一个处理 Room 查询的组件中,并且只在查询返回时显示表单? LiveData<Person> 这个案例会是什么样子?
【问题讨论】:
-
至第 2 点:当您的状态发生变化时,您可以使用 remember(yourState [e.g personFromDb.observeAsState()]) {mutableStateOf(findPersonQueryResult.value)} 计算再次完成
标签: android kotlin state android-jetpack android-jetpack-compose