Vuk*_*bic 55 android android-livedata android-viewmodel android-architecture-components
我有一个单独的类来处理数据提取(特别是Firebase),我通常从它返回LiveData对象并异步更新它们.现在我想将返回的数据存储在ViewModel中,但问题是为了获得所述值,我需要观察从我的数据获取类返回的LiveData对象.observe方法需要一个LifecycleOwner对象作为第一个参数,但我显然没有在我的ViewModel内部,我知道我不应该保持对ViewModel内部的Activity/Fragment的引用.我该怎么办?
小智 22
我认为您可以使用不需要生命周期所有者接口的observeForever,您可以从视图模型中观察结果
Des*_*Lua 19
在ViewModel文档中
但是,ViewModel对象绝不能观察到生命周期感知的可观察对象(例如LiveData对象)的更改.
另一种方法是数据实现RxJava而不是LiveData,然后它不具备生命周期感知的好处.
在todo-mvvm-live-kotlin的 google示例中,它使用ViewModel中没有LiveData的回调.
我猜你是否想要遵守生命周期的整个想法,我们需要在Activity/Fragment中移动观察代码.否则,我们可以在ViewModel中使用回调或RxJava.
另一个折衷方案是在ViewModel中实现MediatorLiveData(或Transformations)并观察(将您的逻辑放在这里).注意MediatorLiveData观察者不会触发(与转换相同),除非在Activity/Fragment中观察到它.我们所做的是在Activity/Fragment中进行空白观察,其中实际工作实际上是在ViewModel中完成的.
// ViewModel
fun start(id : Long) : LiveData<User>? {
val liveData = MediatorLiveData<User>()
liveData.addSource(dataSource.getById(id), Observer {
if (it != null) {
// put your logic here
}
})
}
// Activity/Fragment
viewModel.start(id)?.observe(this, Observer {
// blank observe here
})
Run Code Online (Sandbox Code Playgroud)
PS:我读过ViewModels和LiveData:Patterns + AntiPatterns,它们提出了转换.除非观察到LiveData(可能需要在Activity/Fragment中完成),否则我认为它不起作用.
您可以使用liveDatabuilder 函数调用suspend函数,将结果作为LiveData对象提供。
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
Run Code Online (Sandbox Code Playgroud)
您还可以从块中发出多个值。每次emit()调用都会暂停块的执行,直到LiveData在主线程上设置该值。
val user: LiveData<Result> = liveData {
emit(Result.loading())
try {
emit(Result.success(fetchUser()))
} catch(ioException: Exception) {
emit(Result.error(ioException))
}
}
Run Code Online (Sandbox Code Playgroud)
在您的 gradle 配置中,使用androidx.lifecycle:lifecycle-livedata-ktx:2.2.0或更高版本。
更新:也可以LiveData<YourData>在Dao interface. 您需要suspend在函数中添加关键字:
@Query("SELECT * FROM the_table")
suspend fun getAll(): List<YourData>
Run Code Online (Sandbox Code Playgroud)
并且ViewModel您需要像这样异步获取它:
viewModelScope.launch(Dispatchers.IO) {
allData = dao.getAll()
// It's also possible to sync other data here
}
Run Code Online (Sandbox Code Playgroud)
然而,ViewModel 对象绝不能观察生命周期感知可观察对象的变化,例如 LiveData 对象。
在这个Github issue 中,他描述了应用上述规则的情况是观察到的生命周期感知 observables 由另一个生命周期范围托管。LiveData在ViewModel包含观察中观察没有问题LiveData。
class MyViewModel : ViewModel() {
private val myLiveData = MutableLiveData(1)
init {
viewModelScope.launch {
myLiveData.asFlow().collect {
// Do Something
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
class MyViewModel : ViewModel() {
private val myFlow = MutableStateFlow(1)
private val myLiveData = myFlow.asLiveData(viewModelScope.coroutineContext)
}
Run Code Online (Sandbox Code Playgroud)
在asFlow使一个流,使LiveData激活的开始collect。我认为使用MediatorLiveDataorTransformations和附加虚拟观察者的解决方案在实例中始终观察到使用Flow除了发射值之外的差异。LiveDataViewModel
| 归档时间: |
|
| 查看次数: |
29483 次 |
| 最近记录: |