如何预先准备好 RecyclerView 的 RecycledViewPool 以避免滚动时出现初始抖动?

Usm*_*ana 5 performance android android-recyclerview

我有一个 RecyclerView,其中有 3 种不同的 ViewType。如果我滚动列表,那么对于最初的几个项目,它会在滚动过程中显示抽搐/颤抖。当 RecycledViewPool 填充到最大限制时,由于视图被重用,因此滚动变得平滑。所以,我正在考虑预先准备好 RecycledViewPool。我尝试创建一些视图持有者并在用户开始滚动之前添加到池中。但池显示手动插入视图的计数为 0。当 RecyclerView 本身在滚动时将视图添加到池中时,它会显示正确的计数。我正在使用以下方法来实现此目的。这是个好主意吗?或者有一些更准确的解决方案?

   private void addDummyRecycledViews() {
                  int size = demoAdaptor.getList().size() > 7 ? 7 : demoAdaptor.getList().size();

                RecyclerView.RecycledViewPool recycledViewPool = recyclerView.getRecycledViewPool();
                for (int i = 0; i < size; i++) {
                    BaseViewHolder viewHolder = null;
                    int viewType = demoAdaptor.getItemViewType(i);
                    int recycledViewCount = recycledViewPool.getRecycledViewCount(viewType);
                    AppLogger.d("usm_test_adapter_dummy", "viewType= "+viewType+" ,recycledViewCount= "+recycledViewCount);
                    switch (viewType) {
                        case VIEW_TYPE_SIMPLE:
                            AppLogger.d("usm_test_adapter_dummy", "generate VIEW_TYPE_SIMPLE");
                            viewHolder = demoAdaptor.createSimpleItemViewHolder(recyclerView);
                            break;
                        case VIEW_TYPE_SEARCH:
                            AppLogger.d("usm_test_adapter_dummy", "generate VIEW_TYPE_SEARCH");
                            viewHolder = demoAdaptor.createSearchItemViewHolder(recyclerView);
                            break;
                        case VIEW_TYPE_VIDEO:
                            AppLogger.d("usm_test_adapter_dummy", "generate VIEW_TYPE_VIDEO");
                            viewHolder = demoAdaptor.createVideoItemViewHolder(recyclerView);
                            break;
                    }
                    if (viewHolder != null) {
                        demoAdaptor.onBindViewHolder(viewHolder, i);
                        recycledViewPool.putRecycledView(viewHolder);
                    }

                }
                recyclerView.setRecycledViewPool(recycledViewPool);

        }
Run Code Online (Sandbox Code Playgroud)

Tal*_*tle 0

这可以通过对代码进行一些调整来实现。关键点是:

  1. 增加 RecycledViewPool 的最大回收视图数以适合您想要的数量。
  2. 调用正确的方法来创建视图持有者:调用Adapter.createViewHolder()而不是 Adapter.onCreateViewHolder()。这是必需的,因为一种方法可以设置ViewHolder.mItemViewType,而另一种则不能。
  3. 将正确数量的 ViewHolders 插入池中,记住最初可见的项目可能会消耗 ViewHolders。

例如,如果您预计最初在屏幕上有 6 个项目可见,并且希望池中另外有 4 个项目,则最多可以设置 10 个回收视图。

你可以这样做onCreateView()

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    // ... create your views ...
    
    // initialize some recycled views for smoother initial scrolling
    final int EXPECTED_VISIBLE_INITIALLY = 6;
    final int EXTRA_IN_POOL = 4;
    final int POOL_SIZE = EXPECTED_VISIBLE_INITIALLY + EXTRA_IN_POOL;
    recyclerView.getRecycledViewPool().setMaxRecycledViews(VIEW_TYPE_VIDEO, POOL_SIZE);
    for (int i = 0; i < POOL_SIZE; i++) {
        RecyclerView.ViewHolder viewHolder = adapter.createViewHolder(recyclerView, VIEW_TYPE_VIDEO);
        recyclerView.getRecycledViewPool().putRecycledView(viewHolder);
    }

    return view;
}
Run Code Online (Sandbox Code Playgroud)