android - Jetpack 撰写 : Modify Room data class using TextField

标签 android kotlin state android-jetpack android-jetpack-compose

修改简单值和data class es 使用 EditText非常简单,通常看起来像这样:

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出于多种原因:

  1. 同时 LiveData有一个函数叫做 observeAsState() , 它返回 State<T>而不是 MutableState<T> ,这意味着您不能使用 TextFields 修改它.因此,这不起作用:
    • remember { personFromDb.observeAsState()}
  2. 你不能.copy() Person你从数据库中获取的,因为你的组件将在 Room 查询返回之前呈现,这意味着你不能这样做,因为 Person类实例将被记住为 null :
    • remember { mutableStateOf(findPersonQueryResult.value) }

鉴于此,处理此问题的正确方法是什么?应该包含 TextField 的组件是否被包装在另一个处理 Room 查询的组件中,并且只在查询返回时显示表单?在这个 LiveData<Person> 的案例中会是什么样子? ?

最佳答案

我会用一个副本和一个不可变的数据类来做到这一点

typealias PersonID = Long?
@Entity
data class Person(val firstName: String, val lastName: String) {
    @PrimaryKey(autoGenerate = true)
    val personID: PersonID = null
}
//VM or sth
object VM {
    val liveData: LiveData<Person> = MutableLiveData() // your db call
    val personDao: PersonDao? = null // Pretending it exists
}

@Dao
abstract class PersonDao {
    abstract fun upsert(person: Person)
}

@Composable
fun test() {
    val personState = VM.liveData.observeAsState(Person("", ""))
    TextField(
        value = personState.value.firstName,
        onValueChange = { fName -> VM.personDao?.upsert(personState.value.copy(firstName = fName))}
    )
}

关于android - Jetpack 撰写 : Modify Room data class using TextField,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64028318/

相关文章:

arrays - 如果键不存在,如何使用默认值制作 map ?

Android - Kotlin : return value in async fun

android - 通过适配器更改RecyclerView项目图标

javascript - React 状态值未定义

reactjs - 提交后清除 React 中的表单

Java.lang.NoSuchMethodError : org. json.JSONObject.put

Android:自定义微调器大小问题

reactjs - <Component {...pageProps}/> 如何发挥作用?

java - Android从 Assets 中读取文件并存储在数组列表中

android - 在 Android 中设置来电时的自定义振动