[英]Android viewmodel coroutine pattern
I would like to hear some critics on the way I have implemeneted viewmodel data fetching using coroutine. 我想听听一些批评者对我使用协程实现视图模型数据获取的方式的评论。 My goal is clean way to write ViewModels.
我的目标是编写ViewModels的干净方法。 But isn't it too big of overhead?
但这不是太大的开销吗? I haven't found so far some clean solution.
到目前为止,我还没有找到一些干净的解决方案。 Let me know your tips.
让我知道你的提示。 I wanted to avoid to write
if (!::users.isInitialized)
as it is in the official tutorial . 我想避免像在正式教程中那样编写
if (!::users.isInitialized)
。
class LiveDataLoader <T>{
val liveData = MutableLiveData<T>()
var loaded:Boolean = false
}
abstract class CustomViewModel : ViewModel(){
private val viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
fun <T> get(container: LiveDataLoader<T>, loader: ()->T): LiveData<T>{
if (!container.loaded){
container.loaded = true
uiScope.launch{
container.liveData.postValue(loader.invoke())
}
}
return container.liveData;
}
override fun onCleared() {
super.onCleared()
viewModelJob.cancel()
}
}
class ActivityTodoGroupsViewModel() : CustomViewModel(){
private val groups = LiveDataLoader<MutableList<TaskGroupWithTasks>>()
private val tasks = LiveDataLoader<MutableList<TodoTask>>()
private lateinit var tasksx: MutableLiveData<MutableList<TodoTask>>
fun getTaskGroups() = get(groups){
AppDatabase.db.toDoTasksDAO.getGroupsWithItems()
}
fun getUpcomingTasks() = get(tasks){
val calendar = Calendar.getInstance()
calendar.add(Calendar.DAY_OF_YEAR, -7)
AppDatabase.db.toDoTasksDAO.getRecentTasks(calendar)
}
}
In general it's always good to not expose the Mutable*
types too much. 通常,最好不要公开太多
Mutable*
类型。 This ensures data consistency. 这样可以确保数据的一致性。 Also it seems like you're trying a achieve something similar to
lazy
, so why not use it. 而且似乎您正在尝试实现类似于
lazy
的成就,所以为什么不使用它。
So you could consider an extension function to CoroutineScope
to convert a suspending function to a simple LiveData
: 因此,您可以考虑将
CoroutineScope
的扩展功能转换为将暂停功能转换为简单的LiveData
:
fun <V> CoroutineScope.liveData(
provider: suspend () -> V
) = lazy<LiveData<V>> {
MutableLiveData<V>().apply {
launch {
postValue(provider())
}
}
}
If you also have your ViewModel
implement CoroutineScope
, you could use it as: 如果您还拥有
ViewModel
实现CoroutineScope
,则可以将其用作:
val taskGroups() by liveData {
AppDatabase.db.toDoTasksDAO.getGroupsWithItems()
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.