0

我想要一個嵌套的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()回調,但這可能會導致內存泄漏。

回答

0

我認爲有幾件事情可能會在這裏出錯。一旦我們弄清楚了,我會更新這個答案。

首先,我想確保你打電話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 = ... 
} 

如果以上都沒有效果的,你需要通過做一些鐵桿調試一點點地逐步瀏覽你的代碼,直到你看到事情正在崩潰。這些都是斷點我建議增加:

  1. 適配器的startListening()方法,確保addChangeEventListener()
  2. 適配器的​​方法,確保它被稱爲用正確的值
  3. 走棧,通過你的記憶看並確保您所持有的參考文獻是當前對象而不是來自onStop()
  4. 所有內容正在正確的位置調用?可能不是FirebaseUI或架構組件問題。順便說一下,請確保您使用的是最新的FUI版本3.1.0和AAC版本rc1
+0

下面最新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) –

+0

嗯,這似乎是一個完全不同的問題。確保你使用的是支持lib 26.1.x並且運行'./gradlew clean'。不知道可能會發生什麼。 – SUPERCILEX

+0

是支持庫是26.1.0並且已經嘗試了清理項目。我的應用程序只能運行帶有FUI 3.0.0的拱形組件1.0.0-beta1。每當我嘗試更新其中的任何一個時,它都會崩潰。 –