嵌套的recylerview滞后,而前几个滚动,然后顺利滚动?

时间:2016-03-10 11:24:20

标签: android performance adapter android-recyclerview android-viewholder

我正在使用嵌套的RecyclerView。在垂直RecyclerView内的手段我有多个水平回收者视图

我将适配器附加到父级RecyclerView的onBindViewHolder方法内的水平recylerviews,如下所示。

@Override
public void onBindViewHolder(final MainViewHolder holder, final int position) {
    switch (holder.getItemViewType()) {
        case TYPE_PRODUCT:
            ((ListHolderProduct) holder).itemTitle.setText(browseCategoryHomePageItems.get(position).displayName.toUpperCase());
            ((ListHolderProduct) holder).recyclerView.setAdapter(new CarouselProductsRecyclerAdapter(context
                    , browseCategoryHomePageItems.get(position).products
                    , R.layout.activity_categoryhome_products_grid_item
                    , nestedRecyclerItemClickedListener
                    , position));
            break;
        case TYPE_DEAL:
            ((ListHolderDeal) holder).itemTitle.setText(browseCategoryHomePageItems.get(position).displayName.toUpperCase());
            ((ListHolderDeal) holder).recyclerView.setAdapter(new CarouselDealsRecyclerAdapter(context
                    , browseCategoryHomePageItems.get(position).dealItems
                    , R.layout.activity_categoryhome_deals_grid_item
                    , nestedRecyclerItemClickedListener
                    , position));
            break;
            //few more types like this
    }
}

现在每当我滚动页面时它都会滞后一点,因为我在OnBindViewHolder上将适配器连接到水平的RecyclerView

可以有N个TYPE_PRODUCT或任何类型的水平列表。 意味着可以有更多相同类型的水平列表。

任何想法如何优化这个东西并提高滚动速度。

由于之前每次为列表调用setAdapter,所以它是滞后的。

对此进行更新我正在扩展LinearLayoutManager并且我正在设置extraLayout空间,这已解决了我的问题,但我不知道这是正确的方法我是否设置了额外的空间,如下所示。

 layoutManager.setExtraLayoutSpace(2 * this.getResources().getDisplayMetrics().heightPixels);

以下是自定义布局管理器类

public class PreCachingLayoutManager extends LinearLayoutManager {
private static final int DEFAULT_EXTRA_LAYOUT_SPACE = 600;
private int extraLayoutSpace = -1;
private Context context;

public PreCachingLayoutManager(Context context) {
    super(context);
    this.context = context;
}

public PreCachingLayoutManager(Context context, int extraLayoutSpace) {
    super(context);
    this.context = context;
    this.extraLayoutSpace = extraLayoutSpace;
}

public PreCachingLayoutManager(Context context, int orientation, boolean reverseLayout) {
    super(context, orientation, reverseLayout);
    this.context = context;
}

public void setExtraLayoutSpace(int extraLayoutSpace) {
    this.extraLayoutSpace = extraLayoutSpace;
}

@Override
protected int getExtraLayoutSpace(RecyclerView.State state) {
    if (extraLayoutSpace > 0) {
        return extraLayoutSpace;
    }
    return DEFAULT_EXTRA_LAYOUT_SPACE;
}

}

5 个答案:

答案 0 :(得分:3)

不要每次在adapter中创建水平onBindViewHolder,而是在每个ViewHolder类(ListHolderDeal,ListHolderProduct)中创建适当的适配器。然后在垂直onBindViewHolder的{​​{1}}中,只需替换该适配器的数据,如果水平Recyclerview没有适配器,则使用视图适配器设置它。如果它是剂量,则替换RecyclerView的数据集并调用adapter。使用这种方法,您可以隐式使用适配器池,因此GC可能不会给您带来麻烦。

我希望它有所帮助。

答案 1 :(得分:1)

滚动时我遇到了同样的问题,因为在滚动时加载图像。因此,您需要使用Picasso库来加载图像,并在使用onScrollListener时使用pause_tag

onBindViewHolder中                   Picasso.with(上下文)                         .load(foodData.getRecipe_resize_image_url())                         .resize(宽度,高度)                         .placeholder(R.drawable.empty_image)                         .TAG( “resume_tag”)                         .into(mainViewHolder.food_picture);

onScrollListener

@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
    super.onScrollStateChanged(recyclerView, newState);
    final Picasso picasso = Picasso.with(context);
    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
        picasso.resumeTag("resume_tag");
    } else {
        picasso.pauseTag("resume_tag");
    }

}

答案 2 :(得分:0)

请检查您是否已覆盖getItemViewType(int position)方法,如果没有,请覆盖此方法并说明您的recyclerview要处理的视图类型有多少,从上面的代码中可以看到两种类型的视图{{1} 1}}和TYPE_PRODUCT的其他内容。

这个特殊方法如果覆盖并正确返回类型计数,它可以防止已经可用的类型视图(在回收器缓存中)不必要的布局膨胀,从而大大提高了性能。

例如,实施多个类型化的recyclerview,please refer this

参考:http://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html#getItemViewType%28int%29

希望这会有所帮助!!!如果您有任何问题,请告诉我。感谢。

答案 3 :(得分:0)

RecyclerView使用视图池来阻止重新创建视图以提高性能但是当我们在RecyclerView内使用RecyclerView时,内部RecyclerView有自己的视图池,因此每次都在外部RecyclerView滚动内部RecyclerView充气的每个视图,因为它有一个单独的视图池。

因此,要使用相同的视图,我们需要在外部RecyclerView适配器中添加此代码:

public OuterRecyclerViewAdapter(List<Item> items) {
    //Constructor stuff
    viewPool = new RecyclerView.RecycledViewPool();
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    //Create viewHolder etc
    holder.innerRecyclerView.setRecycledViewPool(viewPool);

}

我从这个有用的article

中找到了这些信息

答案 4 :(得分:0)

在创建ViewHolder时创建适配器,而不是绑定。另外,请注意,有时由于您正在测试的构建变体而发生初始滚动滞后。 Release APK具有更好的性能,因为不再激活在Debug Build上激活的整个调试工具和分析器。我的大多数性能问题已在发行版中解决。