Android 具有复杂房间LiveData的嵌套Recyclerviews
我有一个父对象集合,每个都有一个子对象集合。将它们称为Android 具有复杂房间LiveData的嵌套Recyclerviews,android,kotlin,android-recyclerview,android-livedata,Android,Kotlin,Android Recyclerview,Android Livedata,我有一个父对象集合,每个都有一个子对象集合。将它们称为ParentModels和ChildModels 在屏幕上,我想显示渲染父模型的RecyclerView,每个都包含渲染子模型的RecyclerView 为了避免仅仅因为一个ChildModel的一个属性发生了变化,而让god LiveData重新绘制所有内容,我打算将它们分开 我不知道如何用Recyclerview适配器和支架以及我需要的任何片段和视图模型来构造它。现在我有 class MyFragment: Fragment() {
ParentModel
s和ChildModel
s
在屏幕上,我想显示渲染父模型的RecyclerView,每个都包含渲染子模型的RecyclerView
为了避免仅仅因为一个ChildModel的一个属性发生了变化,而让god LiveData重新绘制所有内容,我打算将它们分开
我不知道如何用Recyclerview适配器和支架以及我需要的任何片段和视图模型来构造它。现在我有
class MyFragment: Fragment() {
private lateinit val mViewModel: FragmentViewModel
// ...
fun onViewCreated(/*...*/) {
val parentAdapter = ParentAdapter()
view.findViewById<RecyclerView>(/*...*/).apply {
adapter = parentAdapter
//...
}
viewModel.getParents().observe(this, Observer {
parentAdapter.setParents(it)
}
}
}
class FragmentViewModel @Inject constructor(repository: RoomRepo): ViewModel() {
mParents: LiveData<List<ParentModel>> = repository.getParents()
fun getParents() = mParents
//...
}
class ParentAdapter: RecyclerView.Adapter<ParentHolder>() {
private lateinit var mParents: List<ParentModel>
fun setParents(list: List<ParentModel>) {
mParents = list
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, /*...*/) {
return ParentHolder(LayoutInflater.from(parent.context).inflate(R.layout.parent, parent, false))
}
override fun onBindViewHolder(holder: ParentHolder, position: Int) {
holder.bind(/*UNKNOWN*/)
}
// ...
inner class ParentHolder(private val mView: View): RecyclerView.ViewHolder(mView) {
fun bind(/*UNKNOWN*/) {
// WHAT TO DO HERE???
}
}
}
我不假思索地写了一个ChildAdapter、ChildHolder和其他一些东西,因为我认为这将是一个微不足道的实现,但在这一点上,我的大脑被什么东西卡住了,我可能看不到明显的东西
我已经根据底层数据正确加载了第一个RecyclerView。但此父recyclerview还需要:
repository.getChildrenByParentId
)让这一切顺利进行
我在网上找到的所有示例似乎都没有帮助,因为它们使用的是没有LiveData的人工示例和一个God片段/活动,它将所有内容都放在一个适配器中。我实际上有一个适配器可以渲染所有内容,使用
DiffUtil
(或其异步版本)类来确保我没有(我引用)“仅仅因为一个子模型的一个属性发生了变化,就重新绘制了所有内容”
我将把构建(和提供)数据的复杂职责转移到您的存储库(或者,如果您更愿意,转移到您的ViewModel,作为一个或多个(我不知道您的模型看起来如何,所以我只是在想象)提供数据的存储库
这将允许您向ui提供一个更精确的不可变列表,其中包含父级和子级
,而您的RecyclerView/适配器的职责突然变得更简单,显示它,并为每一行绑定正确的视图。您的ui突然变得更快,在主线程上做事情的时间更少,您甚至可以nit测试创建此列表的逻辑,完全独立于您的活动/片段
我想象父母和孩子是这样的:
class ParentChildren(父:父?、子:子?
当父项不为null而子项为null时,绑定可能会膨胀一个视图。当子项不为null时,您知道它是子项(您也可以包括父项,这取决于您如何构造此数据)。问题在此处解决,您的适配器将如下所示
class YourAdapter : ListAdapter<ParentChildren, RecyclerView.ViewHolder>(DiffUtilCallback()) {
...
我将有一个抽象的基础来进一步简化适配器:
internal abstract class BaseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
abstract fun bind(data: ParentChildren)
}
这可以让你拥有你的
// I'm writing pseudo code here... keep it in mind
internal class ParentViewHolder(itemView: View) : BaseViewHolder(itemView) {
private val name: TextView = itemView.findViewById(R.id.item_text)
override fun bind(data: ParentChildren) {
name.text = parentChildren.parent?.name
}
}
internal class ChildrenViewHolder(itemView: View) : BaseViewHolder(itemView) {
private val name: TextView = itemView.findViewById(R.id.item_text)
override fun bind(data: ParentChildren) {
name.text = parentChildren.children?.name
}
}
你明白了
现在…ListAdapter
有一个名为submitList(T)
的方法,其中T是上述伪示例中适配器的类型ParentChildren
这就是我要说的,现在您必须通过LiveData或任何您喜欢的架构来提供承载此适配器的活动或片段列表
它可以是一个存储库,将其传递给viewModel中的可变LiveData,而viewModel公开了一个
LiveData。这就是我最后做的。它工作得很好!不知道DiffUtilGood!:)祝你好运!
internal abstract class BaseViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
abstract fun bind(data: ParentChildren)
}
// I'm writing pseudo code here... keep it in mind
internal class ParentViewHolder(itemView: View) : BaseViewHolder(itemView) {
private val name: TextView = itemView.findViewById(R.id.item_text)
override fun bind(data: ParentChildren) {
name.text = parentChildren.parent?.name
}
}
internal class ChildrenViewHolder(itemView: View) : BaseViewHolder(itemView) {
private val name: TextView = itemView.findViewById(R.id.item_text)
override fun bind(data: ParentChildren) {
name.text = parentChildren.children?.name
}
}