如何在具有嵌套 RecyclerView 的多视图适配器上正确使用 RecycledViewPool?

M'a*_*der 5 android adapter kotlin android-recyclerview nestedrecyclerview

我的应用程序上下文,以便您可以理解我的问题:

我目前正在编写一个非常复杂的应用程序,其中包含一个巨大的仪表板,其中包含大量嵌套的 RecyclerView(水平和垂直)。我知道垂直房车内的垂直房车是一种不好的做法,但不幸的是,这里的管理层和客户的要求比我们的建议更强烈,他们真的希望它得到实施。我们是如何获得垂直房车中的垂直房车的?我们的后端基本上提供了需要在仪表板内呈现的组的数组列表。基本上是服务器驱动的用户界面。这些组包含各种不同的设计、垂直子列表、水平子列表等。到目前为止,我已经成功地为这个 DashBoard 适配器构建了一个原型,现在我想更深入地了解性能优化。

我尝试过提高性能的事情:

我已经实现了 DiffUtil 来使仪表板在数据刷新时更有效地更新。我已将适配器设置为使用每个组都有的稳定 ID 和唯一的哈希值。我已经使用constraintLayout创建了平面UI,并且布局可能绝对最少。我已经使用了数据绑定,事实证明它实际上只提高了一点性能,而不仅仅是更好的干净代码。我绝对没有在适配器或 viewHolder 中进行任何数据处理,整个数据流具有来自更高数据层的最终形状。我已linearLayoutManager.initialPrefetchItemCount = x在每个嵌套 RV 上设置,其中 x 是在任何滚动之前在屏幕上呈现的项目数。

然后我遇到了 RecycledViewPool。我见过一些人们用这个技巧提高列表性能的例子。基本上,他们获取父大适配器的 recyclerViewPool 并将其设置在嵌套的 RV 上。我也实现了这个,我的大问题是现在我所有的嵌套项目都完全混淆了。

而不是像这样拥有三个水平房车:

在此输入图像描述

现在我把它们都混在一起了,如下所示:

在此输入图像描述

这是我的recycledViewPool实现:

class GlobalAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

private val groups: ArrayList<Group> = ArrayList()

private var recyclerViewPool = RecyclerView.RecycledViewPool()

[...]

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    return when (viewType) {
        CATEGORIES_LIST.typeText.hashCode() -> {
            val holder = CategoryGroupViewHolder(
                DataBindingUtil.inflate(
                    LayoutInflater.from(parent.context),
                    R.layout.group_item_categories_list, parent, false
                ), adapterCallback
            )
            holder.binding.recyclerView.setRecycledViewPool(recyclerViewPool)
            holder
        }
     
        [...]
Run Code Online (Sandbox Code Playgroud)

所以我基本上将 viewPool 设置为 onCreateViewHolder 中的嵌套 RV。最重要的是,遵循这篇文章:https://medium.com/@thagikura/reduce-the-number-of-inflation-of-viewholders-drastically-by-sharing-a-viewpool-across-multiple-249d5fc6d28我还在视图持有者中做了以下事情:

class CategoryGroupViewHolder(
   val binding: GroupItemCategoriesListBinding,
   private val adapterCallback: adapterCallback?
):
RecyclerView.ViewHolder(binding.root) {

private val categoryAdapter = CategoryAdapter()
private val defaultItemAnimator = DefaultItemAnimator()
private val linearLayoutManager = LinearLayoutManager(
    binding.root.context, LinearLayoutManager.HORIZONTAL, false
)

fun bind(group: Group) = with(binding.root) {
    binding.categoryGroup = group
    binding.executePendingBindings()
    linearLayoutManager.initialPrefetchItemCount = 5
    binding.recyclerView.apply {
        adapter = categoryAdapter
        linearLayoutManager.recycleChildrenOnDetach = true
        layoutManager = linearLayoutManager
        itemAnimator = defaultItemAnimator
    }
}
Run Code Online (Sandbox Code Playgroud)

注意linearLayoutManager.recycleChildrenOnDetach = true。我在这里做错了什么以及为什么我的物品在整个适配器中完全混合在一起。有关如何正确使用此功能的任何建议recycledViewPool

另外,如果你们中的任何人对如何优化垂直recyclerView中的垂直recyclerView有一些建议,我们将非常感激。谢谢

小智 0

如果我没有记错的话,我认为在这里使用 ConcatAdapter 会以更简单的方式解决您的问题。如果您寻找示例,可以查看我的存储库。

https://github.com/cnrture/ConcatAdapterExample