【问题标题】:Nested RecyclerView Prefetch not working on initial scroll only嵌套的 RecyclerView Prefetch 仅在初始滚动时不起作用
【发布时间】:2019-01-11 16:40:51
【问题描述】:

所以我的问题是我有一个垂直回收器视图,其中包含多行嵌套的水平回收器视图。我在嵌套的 recyclerviews 上启用了预取并将初始预取计数设置为 20(用于测试),但是,在外部适配器的 onBindViewHolder 中添加项目时,由于内部 recyclerview 适配器上的挂起更新,它不会在初始向下滚动时进行预取。这是我的外部适配器代码。每个“块”都是一个水平滚动视图

private class BlockAdapter(val blocks: List<Block>) : RecyclerView.Adapter<VH>() {
    private val viewCreatorsByType = HashMap<Int, Block>()

    override fun getItemViewType(position: Int): Int {
        val block = blocks[position]
        val blockKey = block.viewType.ordinal
        viewCreatorsByType[blockKey] = block
        return blockKey
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
        val block = viewCreatorsByType[viewType]!!
        return VH(block.createView(parent.context, parent))
    }

    override fun onBindViewHolder(holder: VH, position: Int) {
        holder.index = position
        holder.boundPresenter = blocks[position].presenter.apply {
            attachView(holder.view)
            resume()
            present()
        }
    }

    override fun onViewRecycled(holder: VH) {
        holder.boundPresenter?.run {
            pause()
            detach()
        }
        holder.boundPresenter = null
    }

    override fun getItemCount(): Int = blocks.size
}

class VH(val view: android.view.View) : RecyclerView.ViewHolder(view) {
    var boundPresenter: Presenter? = null
    var index: Int = 0
}

在 onBindViewHolder 中调用 present 时,会填充内部适配器并将卡片添加到内部水平回收器视图适配器,但由于水平回收器视图适配器上的未决更新而无法预取。这可以在 GapWorker 类中找到 ->

        void collectPrefetchPositionsFromView(RecyclerView view, boolean nested) {
        mCount = 0;
        if (mPrefetchArray != null) {
            Arrays.fill(mPrefetchArray, -1);
        }

        final RecyclerView.LayoutManager layout = view.mLayout;
        if (view.mAdapter != null
                && layout != null
                && layout.isItemPrefetchEnabled()) {
            if (nested) {
                // nested prefetch, only if no adapter updates pending. Note: we don't query
                // view.hasPendingAdapterUpdates(), as first layout may not have occurred 
                if (!view.mAdapterHelper.hasPendingUpdates()) { //<-This is where prefetch is failing initially since the horizontal list adapter is has a pending "add" update. 
                    layout.collectInitialPrefetchPositions(view.mAdapter.getItemCount(), this);
                }
            } else {
                // momentum based prefetch, only if we trust current child/adapter state
                if (!view.hasPendingAdapterUpdates()) {
                    layout.collectAdjacentPrefetchPositions(mPrefetchDx, mPrefetchDy,
                            view.mState, this);
                }
            }

            if (mCount > layout.mPrefetchMaxCountObserved) {
                layout.mPrefetchMaxCountObserved = mCount;
                layout.mPrefetchMaxObservedInInitialPrefetch = nested;
                view.mRecycler.updateViewCacheSize();
            }
        }
    }

布局后,我可以向上滚动并按预期进行预取,但这对向下滚动时的初始卡顿没有帮助。有解决这个问题的办法吗?

【问题讨论】:

  • 我不知道我是否理解正确:所以你有一个RecyclerView 并且你想添加一个项目然后onBindViewHolder 你想获取更多项目?或者你只想要可见的项目?
  • 我有一个垂直回收器视图,其中包含多行水平回收器视图,因此您可以在垂直列表上向上/向下滚动,然后在每个水平列表上向左/向右滚动。
  • 我还在问题跟踪器中创建了一个问题。它包含演示该问题的示例代码。 issuetracker.google.com/issues/122712979
  • @ReidMacif 如果您解决了这个问题,请更新答案,因为我面临同样的问题。谢谢。
  • @RaoArsalan 我希望我有一个答案给你,但唉,我没有。从那以后我就离开了那个项目。

标签: android android-recyclerview android-adapter


【解决方案1】:

我认为您应该有一个持有人视图,然后创建水平的RecyclerView,然后使用horizontalListHolder.addView(yourHorizontaRecyclerView) 将它们一一添加到该持有人,其中horizontalListHolder 可以是ScrollView 内的垂直LinearLayout 所以你的布局看起来像这样:

<ScrollView
    android:orientation="vertical">
    <LinearLayout
        android:orientation="vertical"
        android:id="@+id/horizontalListHolder">
        <--add your horizontal recyclerViews here !->
   </LinearLayout>

</ScrollView>

希望对你有帮助

【讨论】:

  • 感谢您的回复,不过,我需要使用回收站视图。 ScrollViews 在这种情况下不起作用。出于性能原因,我们需要能够回收水平回收器视图。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-17
  • 2020-09-07
  • 1970-01-01
相关资源
最近更新 更多