【问题标题】:PagingDataAdapter stops loading after fragment is removed and added back删除片段并重新添加后,PagingDataAdapter 停止加载
【发布时间】:2021-05-22 13:54:03
【问题描述】:

我在 PagingDataAdapter 上展示 Room ORM 返回的 PagingSource

RecyclerView 存在于片段上——我有两个这样的片段。当它们被切换时,它们会停止加载下一页上的项目,并且在滚动时只显示占位符。

如果不清楚我的意思,请查看这些屏幕截图--

相关代码(请询问您是否想查看其他部分/文件)-

片段:

private lateinit var recyclerView: RecyclerView
private val recyclerAdapter = CustomersAdapter(this)

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    recyclerView = view.findViewById(R.id.recycler_view)
    recyclerView.adapter = recyclerAdapter
    recyclerView.layoutManager = LinearLayoutManager(context)

    viewLifecycleOwner.lifecycleScope.launch {
        viewModel.customersFlow.collectLatest { pagingData ->
           recyclerAdapter.submitData(pagingData)
        }
    }
}

查看模型-

class CustomersListViewModel(application: Application, private val debtOnly: Boolean): ViewModel() {

    private val db = AppDatabase.instance(application)
    private val customersDao = db.customersDao()

    val customersFlow = Pager(PagingConfig(20)) {
        if (debtOnly)
            customersDao.getAllDebt()
        else
            customersDao.getAll()
    }.flow.cachedIn(viewModelScope)
}

【问题讨论】:

  • 告诉我TestApp源代码,我可以帮你解决问题。
  • @DucThang 感谢您的帮助!我这里推送源代码请查看:github.com/quanta-kt/SMJ-App/tree/master
  • 好的,@Quanta 让我检查一下!
  • 我已经回答了你的问题,请检查是否正常

标签: android android-fragments android-recyclerview android-room android-paging


【解决方案1】:

看完你的代码,发现问题FragmentTransaction.replace函数和flow.cachedIn(viewModelScope) 当activity调用replacefragment函数时,CustomerFragment会被销毁,它的ViewModel也会被销毁(viewModel.onCleared()被触发)所以这次cachedIn(viewModelScope)也是无效的。

我有 3 个解决方案给你

解决方案 1:删除 .cachedIn(viewModelScope)

请注意,这只是一个临时解决方案,不推荐。 因此,Activity 上仍然存在 Fragment 实例,但 Fragment 已销毁(内存仍在泄漏)。

解决方案 2:不要在 Main 活动中使用 FragmentTransaction.replace 函数,而是使用 FragmentTransaction.add 函数

它不会泄漏内存,仍然可以使用cachedIn 函数。应该在activity的fragment少且fragment的视图不太复杂的情况下使用。

private fun switchNavigationFragment(navId: Int) {
    when (navId) {
        R.id.nav_customers -> {
            switchFragment(allCustomersFragment, "Customer")
        }
        R.id.nav_debt -> {
            switchFragment(debtCustomersFragment, "DebtCustomer")
        }
    }
}

private fun switchFragment(fragment: Fragment, tag: String) {
    val existingFragment = supportFragmentManager.findFragmentByTag(tag)
    supportFragmentManager.commit {
        supportFragmentManager.fragments.forEach {
            if (it.isVisible && it != fragment) {
                hide(it)
            }
        }
        if (existingFragment != fragment) {
            add(R.id.fragment_container, fragment, tag)
                .disallowAddToBackStack()
        } else {
            show(fragment)
        }
    }
}

解决方案 3:使用导航组件 Jetpack

这是最安全的解决方案。 可以使用Android Studio的模板或者下面的一些文章来创建。

Navigation UI

A safer way to collect flows

我尝试了解决方案 1 和 2,结果如下:

【讨论】:

  • 太棒了!非常感谢详细解答!明天早上我一定会试试的,现在很累,很沮丧
  • 整洁。您能否简要指出为什么需要disallowAddToBackStack() 电话?
  • 其实,不需要它,它仍然可以正常工作,这是我的一个旧项目的代码。您可以在以下位置查看更多信息:developer.android.com/reference/android/app/…
  • 我想防止一些粗心的调用它添加到fragment堆栈,当按下它不会返回到上一个fragment,而是会退出应用程序。
猜你喜欢
  • 1970-01-01
  • 2015-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-29
  • 1970-01-01
相关资源
最近更新 更多