我试图有一个嵌套的RecyclerView,其中水平RecyclerView将显示为垂直RecyclerView的一个项目。(UI看起来类似于Google Play商店)
由于我的数据集在FirebaseFirestore中,因此我使用FirestoreRecyclerAdapter来实现这一点。
My Fragment的代码(Parent RecyclerView存在于此处):
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val view = inflater.inflate(R.layout.layout_recyclerview, container, false)
val query = <some reference>
val recycler = view.recyclerView
recycler.setHasFixedSize(true)
adapter = DashboardAdapter(this,
FirestoreRecyclerOptions.Builder<Category>().categoryOption(query, this),
R.layout.item_dashboard_row)
recycler.adapter = adapter
return view
}
DashboardAdapter代码段:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DashboardHolder {
val item = LayoutInflater.from(parent.context)
.inflate(layout, parent, false)
return DashboardHolder(item)
}
DashboardHolder代码段:
internal class DashboardHolder(item: View) : RecyclerView.ViewHolder(item) {
private val rowTitle: TextView = item.rowTitle
private val rowRecycler: RecyclerView = item.rowRecycler
fun bind(category: Category, owner: LifecycleOwner) {
rowTitle.text = category.name
rowRecycler.setHasFixedSize(true)
val query = <some query>
val adapter = DashboardProductsAdapter(
FirestoreRecyclerOptions.Builder<Product>()
.productOption(query, owner),
R.layout.item_dashboard_product)
rowRecycler.adapter = adapter
}
}
很明显,DashboardHolder(父视图持有者)中有RecyclerView。在绑定时,子适配器被创建并设置为子RecyclerView。
当我第一次加载Fragment时,一切都很好,加载正常。但是当我单击Home按钮并再次返回应用程序时,只有父RecyclerView被填充,而不是子RecyclerView。
在我开始深入挖掘之后,发现这是因为我在创建FirestoreRecyclerOptions
时传递了LifecycleOwner
。如果我不设置它并手动调用startListening()
和stopListening()
,那么行为也是一样的。但是如果我不调用stopListening()
,它就可以正常工作。
更新了Fragment的代码:
override fun onStart() {
super.onStart()
adapter.startListening()
}
override fun onStop() {
super.onStop()
// If I comment this out, everything works fine
// But putting this in code doesn't populate the child RecyclerView 2nd time
adapter.stopListening()
}
可能的问题是什么?我是否应该在bind()方法之外创建子适配器?我是否应该跳过stopListening()
回调,但这可能会导致内存泄漏。
2条答案
按热度按时间ldxq2e6h1#
我认为有几件事可能会出错。一旦我们弄清楚了,我会更新这个答案。
首先,我想确定您是在
onBindViewHolder()
中调用bind()
,对吗?接下来,我很确定这并不重要,但是你可以像这样将你的init代码移动到
onViewCreated()
:对于视图持有者来说,有一个核心问题需要解决,这个问题有点棘手。
bind()
将在onStart()
和onStop
之间被调用无数次,这意味着你将留下大量的挂起适配器,因为当适配器被反弹时,stopListening()
不会被调用。为了解决这个问题,你需要将适配器保存在一个属性中,并在bind()
中每次清除它,如下所示:如果以上都不起作用,你需要做一些核心调试,一点一点地单步调试代码,直到你看到哪里出了问题。我建议添加以下断点:
1.适配器的
startListening()
方法,确保调用了addChangeEventListener()
1.适配器的
onChildChanged()
方法,确保使用正确的值调用该方法1.遍历堆栈以查看内存,并确保所持有的引用是当前对象,而不是来自
onStop()
的ghost1.一切都在正确的地方调用?可能不是FirebaseUI或架构组件的问题。顺便说一句,确保您使用的是最新的FUI版本
3.1.0
和AAC版本rc1
。gr8qqesn2#
我刚刚在两个recyclerView对象上调用了setHasFixedSize(false),它对我很有效。