我的活动有一个Google的ViewModel,它可以获取一些模型项。然后将这些项目转换为RecyclerView的适配器项目。一个RecyclerView还支持许多类型的适配器项。
我想为每个这些模型对象有一个单独的视图模型对象,这样我可以将更复杂的逻辑仅封装在该“小”视图模型中。
[当前,当我有一些仅与某些适配器项有关的异步逻辑(需要在onCleared()中停止)时,我必须以某种方式通过主视图模型路由回调,以便正确地注销所有内容。
我曾考虑使用ViewModelProvider::get(key, modelClass)
,但我的商品随着时间的推移而变化,我找不到找到清除旧物件的好方法。
您如何在项目中处理这些情况?
编辑:要添加有关我的关注的更多信息,也许用不同的词:我希望我的“小” ViewModel能够在它代表的模型项的范围内生存。这意味着:
编辑:请尝试将其与带有Fragments作为项目的ViewPager进行比较。每个单独的模型项都用其ViewModel表示为片段。我想实现类似的功能,但要使用RecyclerView。
为什么?
[ViewModel
是AAC ((Android体系结构组件)],其唯一目的是在Android Activity / Fragment生命周期的配置更改中幸存下来,以便在这种情况下可以通过ViewModel保留数据。
这就是为什么不应该在RecyclerView ((ViewHolder)项目上使用它,因为Item View本身将是Activity / Fragment的一部分,并且它(RecyclerView / ViewHolder)不包含任何特定的API提供ViewModelStoreOwner
(从中基本派生给定Activity / Fragment实例的ViewModels。
获得ViewModel的简单语法是:
ViewModelProvider(this).get(ViewModel::class.java)
&这里this
将被称为活动/片段上下文。
因此,即使您最终在ViewModel
项目中使用了RecyclerView
,由于上下文可能是Activity / Fragment在RecyclerView中是相同的,这也会给您带来相同的实例,这对我来说没有意义。因此,ViewModel对于RecyclerView无效,或者对这种情况没有太大帮助。
解决方案?
您可以直接从LiveData
类中的活动/片段的ViewModel
中传递需要观察的RecyclerView.Adapter
对象。您还需要为适配器提供LifecycleOwner
,以开始观察给定的实时数据。
所以您的Adapter类如下所示:
class RecyclerViewAdapter(private val liveDataToObserve: LiveData<T>, private val lifecycleOwner: LifecycleOwner) : RecyclerView.Adapter<ViewHolder>() {
init {
liveDataToObserve.observe(lifecycleOwner) { t ->
// Notify data set or something...
}
}
}
如果不是这种情况,并且您想在ViewHolder
类中使用它,则可以在LiveData
方法期间将onCreateViewHolder
对象与lifecycleOwner
一起传递给ViewHolder实例。
奖励点!
如果在RecyclerView项上使用数据绑定,则可以轻松地从绑定类中获取lifecyclerOwner
对象。您所需要做的就是在onCreateViewHolder()
期间进行设置,如下所示:
class RecyclerViewAdapter(private val liveDataToObserve: LiveData<T>, private val lifecycleOwner: LifecycleOwner) : RecyclerView.Adapter<ViewHolder>() {
override fun onCreateViewHolder: ViewHolder {
// Some piece of code for binding
binding.lifecycleOwner = [email protected]
// Another piece of code and return viewholder
}
}
class ViewHolder(private val someLiveData: LiveData<T>, binding: ViewDataBinding): RecyclerView.ViewHolder(binding.root) {
init {
someLiveData.observe(requireNotNull(binding.lifecycleOwner)) { t->
// set your UI by live data changes here
}
}
}
所以是的,您可以为ViewHolder
实例使用包装器类来为您提供LiveData
,但如果包装器类扩展了ViewModel
类,我不建议这样做。
[一旦考虑模仿onCleared()
的ViewModel
方法,您可以在包装类上创建一个方法,该方法在ViewHolder
回收或通过方法onViewRecycled()
或onViewRecycled()
从窗口分离时被调用)最适合您的情况。