与FirestoreRecyclerAdapter和LifecycleOwner嵌套RecyclerView不会填充
我想要一个嵌套的RecyclerView其中一个水平的RecyclerView将显示为垂直RecyclerView的项目。 (UI与Google Play Store类似)与FirestoreRecyclerAdapter和LifecycleOwner嵌套RecyclerView不会填充
由于我的数据集位于FirebaseFirestore中,因此我使用FirestoreRecyclerAdapter来实现此目的。
我的片段的代码(家长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。
当我第一次加载碎片时,一切正常,加载正常。但是,当我点击主页按钮并再次回到应用程序,只有父RecyclerView被填充,而不是孩子。
我开始挖掘更多后,发现这是因为LifecycleOwner
我正在创建FirestoreRecyclerOptions
。如果我没有设置并手动拨打startListening()
和stopListening()
,那么行为也是一样的。但如果我不打电话stopListening()
,它工作正常。
更新片段的代码:
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()
回调,但这可能会导致内存泄漏。
我认为有几件事情可能会在这里出错。一旦我们弄清楚了,我会更新这个答案。
首先,我想确保你打电话bind()
在onBindViewHolder()
,对不对?
接下来,我敢肯定,这并不重要,但你能不能将你的初始化代码onViewCreated()
像这样:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
inflater.inflate(R.layout.layout_recyclerview, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
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
}
至于你的观点持有者,有一个核心的问题,您需要解决这个问题有点棘手。 bind()
将在onStart()
和onStop
之间被多次调用,这意味着您将剩下大量的挂接适配器,因为当适配器被反弹时stopListening()
不会被调用。为了解决这个问题,你需要保存在你的财产适配器和每次清除它在bind()
像这样:
private var currentAdapter: FirestoreRecyclerAdapter<...>? = null
fun bind(...) {
currentAdapter?.let {
it.stopListening() // Stop listening to database
lifecycle.removeObserver(it) // Prevent automatic readdition of listeners
}
// Init adapter
currentAdapter = ...
}
如果以上都没有效果的,你需要通过做一些铁杆调试一点点地逐步浏览你的代码,直到你看到事情正在崩溃。这些都是断点我建议增加:
- 适配器的
startListening()
方法,确保addChangeEventListener()
叫 - 适配器的方法,确保它被称为用正确的值
- 走栈,通过你的记忆看并确保您所持有的参考文献是当前对象而不是来自
onStop()
- 所有内容正在正确的位置调用?可能不是FirebaseUI或架构组件问题。顺便说一下,请确保您使用的是最新的FUI版本
3.1.0
和AAC版本rc1
。
下面最新FUI例外:了java.lang.RuntimeException:java.lang.NoSuchMethodException: [类com.firebase.ui.firestore.FirestoreRecyclerAdapter] 在android.arch.lifecycle.ja(Lifecycling.java: 111) at android.arch.lifecycle.ja(Lifecycling.java:57) at android.arch.lifecycle.h $ a。 (LifecycleRegistry.java:346) at android.arch.lifecycle.h.a(LifecycleRegistry.java:162) at com.firebase.ui.firestore.FirestoreRecyclerAdapter。 (FirestoreRecyclerAdapter.java:37) –
嗯,这似乎是一个完全不同的问题。确保你使用的是支持lib 26.1.x并且运行'./gradlew clean'。不知道可能会发生什么。 – SUPERCILEX
是支持库是26.1.0并且已经尝试了清理项目。我的应用程序只能运行带有FUI 3.0.0的拱形组件1.0.0-beta1。每当我尝试更新其中的任何一个时,它都会崩溃。 –