android - 观察从后台线程进行的数据库对象更改
问题描述
我遇到了在我的应用程序中观察数据的问题。
出于测试目的,我有一个带有单个文本视图的活动,其中显示了用户名。这是代码:
@Entity(tableName = "User")
data class User(
var name: String,
var surname: String,
@PrimaryKey(autoGenerate = true)
val internalID: Long = 0)
在 dao 中,我只有一种方法:
@Query("SELECT * FROM User WHERE surname LIKE :surname")
abstract suspend fun getUserForSurname(surname: String): User
在活动 onCreate 的方法中:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
val model = ViewModelProvider(this).get(MainViewModel::class.java)
binding.viewmodel = model
model.user.observe(this, Observer {
binding.textTest.setText(it.name)
})
}
最后,查看模型:
class MainViewModel(application: Application) : AndroidViewModel(application) {
private val surname = "Doe"
val user: MutableLiveData<User> = MutableLiveData()
private val userDao: UserDao =
MyRoomDatabase.getDatabase(application).clientDao()
init {
viewModelScope.launch {
user.value = userDao.getUserForSurname(surname)
}
}
}
该特定用户的名称在后台线程中更改。当我检查 db 本身的值时,名称确实不同。重新启动活动后,文本视图也发生了变化。换句话说:db 值改变了,但观察者永远不会被调用。我知道我在 viewmodel 的 init 方法中只要求一次该值,这可能是一个问题。是否可以在不重新启动活动的情况下查看实际更改?
解决方案
我建议你看看这个Codelab
Room 在返回的实体周围暴露了不同的包装器,例如:
- RxJava
- 流协程
- 实时数据
所以你可以这样改变你的道:
@Query("SELECT * FROM User WHERE surname LIKE :surname")
abstract fun getUserForSurname(surname: String): LiveData<User>
以上意味着对用户条目的任何更改都会向 LiveData 的侦听器发出观察结果。
视图模型
class MainViewModel(application: Application) : AndroidViewModel(application) {
private val surname = "Doe"
lateinit val client: LiveData<User>
private val userDao: UserDao =
MyRoomDatabase.getDatabase(application).clientDao()
init {
viewModelScope.launch {
user = userDao.getUserForSurname(surname)
}
}
}
阅读更多: - https://developer.android.com/training/data-storage/room/index.html
免责声明:没有测试上述解决方案,但它应该给你一个想法。
编辑:理想情况下,LiveData应该只在您的视图模型中使用,因为它们是为这种情况设计的,而不是观察数据库事务。我会建议将 Dao 替换为 Coroutine 的 Flow 并使用扩展转换为 LiveData。
推荐阅读
- javascript - 仅对单击按钮调用一次做出反应,然后单击它不会更新
- android - MediaPlayer:无法打开文件 java.io.FileNotFoundException:没有内容提供者:
- javascript - 如何调用从不同文件返回承诺的函数
- javascript - JavaScript const 和 let 作用域语法有效性
- css - 像素艺术的 CSS box-shadow 或普通图像文件?
- c# - 实体指定关系
- ios - Swift iOS:将视频保存到库
- javascript - 使用 javascript for 循环在 TD 内创建跨度
- javascript - 如何将 TWA 的 javascript 代码绑定到本机函数?
- json - 如何以我需要的形式获取数据?