gpt4 book ai didi

android - 您如何使用 Room 和带有 LiveData 的 ViewModel 检索树结构,以便在包含子 RecyclerView 的 RecyclerView 中使用?

转载 作者:行者123 更新时间:2023-12-02 12:58:39 25 4
gpt4 key购买 nike

我正在尝试检索一个项目列表,其中每个项目还可以包含 Room 数据库中的子项目(树结构)。我想在 RecyclerView 中使用这些项目,这取决于该项目是否有子项目本身会产生另一个 RecyclerView 以包含这些子项目。我遇到的问题是如何将这些项目正确检索为 LiveData。在数据库中,每个项目都有一个指向项目父级的 parent_id。

@Entity(
tableName = "items_table",
foreignKeys = [ForeignKey(entity = Item::class,
parentColumns = ["id"],
childColumns = ["parent_id"],
onDelete = ForeignKey.CASCADE)])
data class Item(
@PrimaryKey(autoGenerate = true)
var id: Int,
var parent_id: Int?,
var name: String
... // Additional fields
)

我现在使用“getRoot”和“getChildren”通过 DAO 检索项目:

@Dao
interface ItemsDao{
@Query("SELECT * FROM items_table WHERE parent_id=:parent_id")
fun findChildItems(parent_id: Int): LiveData<List<Item>>

@Transaction
@Query("SELECT * FROM items_table WHERE parent_id IS NULL")
fun getRoot(): LiveData<Item>
}

项目和子项目现在应该使用 RecyclerView 的适配器

class ItemListAdapter(...) : RecyclerViewAdapter<ItemViewHolder> {

override fun getItemViewType(someItem): Int {
return when someItem.hasChildren {
true -> 0
false -> 1
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder{
val layoutInflater = LayoutInflater.from(parent.context)
when (viewType) {
0 -> { // Item has children
val inflated = // inflated with new recyclerView
return ItemViewHolder(inflated, 0)
}
else -> { // Item has no children
val inflated = // layout without new recyclerView
return itemViewHolder(inflated, 1)
}
}
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int)
// [...]
when (holder.type) {
0 -> {
// Customize the view
holder.itemView.recyclerView.adapter = ItemListAdapter(..., context)
}
else -> {
// Customize the view
}
}
}
}

由于我的数据库是使用 ViewModel 访问的,而 Adapter 没有访问 ViewModel 的权限,我如何将包含子项的项及其各自的子项等与包含各自子项的 LiveData 一起提供?我应该只将 Dao 还是 viewModel 传递给适配器。在那种情况下,我如何从适配器内部观察 LiveData,因为它不是 fragment/Activity ?有更好的解决方案吗?

最佳答案

这不是一个完美的答案,我认为有更好的方法(也许至少使用 transformations ),但它目前有效。

我没有使用数据库加载子项,而是简单地观察 LiveData 列表并在它发生变化时转换它以加载到适配器中:

在 fragment/Activity 中:

viewModel = ViewModelProviders.of(this).get(ItemViewModel::class.java)

viewModel.items.observe(this, Observer {items ->
val rootItem = items.filter { it.parent_id == null }
for (item in rootItem) //There should be only one root item but filter returns a list
item.populateChildren(items)
adapter.setItems(rootItem)
})

实体包含一个方法“populateChildren(subList: List)”,它递归地填充项目中的@Ignore'd 字段,创建一个以 rootItem 开始并通过其子项访问的树结构:

@Entity(
tableName = "items_table",
foreignKeys = [ForeignKey(entity = Item::class, parentColumns = ["id"], childColumns = ["parent_id"], onDelete = ForeignKey.CASCADE)])
data class Item(
@PrimaryKey(autoGenerate = true)
var id: Int,
var parent_id: Int?,
var name: String){
@Ignore var children: List<Item> = emptyList()

fun populateChildren(items: List<Item>){
children = items.filter { it.parent_id == this.id }
for (child in children)
child.populateChildren(items)
}

}

此方法只是执行数据库对“findChildItems()”所做的操作,并将列表中项目的父 ID 与父 ID 匹配。

适配器包含一个“setItems()”方法,该方法目前使用“notifyDataSetChanged()”(不确定 atm 如何正确更新它)。

internal fun setItems(sItems: List<Item>) {
subList = sItems
notifyDataSetChanged()
}

现在在适配器的 onBindViewHolder 中,我将子级传播到新的 recyclerView:

override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val viewItem = holder.itemView
val item : Item = subList[position]
when (holder.type) {
0 -> { // has children
// Update viewItem
// viewItem.[...] = item.[...]
viewItem.recyclerView.layoutManager =
LinearLayoutManager(context)
viewItem.recyclerView.adapter = ItemAdapter(item.children, context)
}
else -> { // no Children
val viewItem = holder.itemView
// Update viewItem
// viewItem.[...] = item.[...]
}
}
}

适配器列表也可以在实例化时设置:

class ItemAdapter(var subList: List<Item>, val context: Context) : RecyclerView.Adapter<ItemViewHolder>() {

关于android - 您如何使用 Room 和带有 LiveData 的 ViewModel 检索树结构,以便在包含子 RecyclerView 的 RecyclerView 中使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56298770/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com