RecyclerView列表嵌套列表卡顿问题

需求

最近有一个需求是编写一个列表展示页,但是列表是分类展示的,每一个分类下也是一组数据,可以认为也是一个列表

列表展示页

实现思路

目前的做法就是 RecyclerView 嵌套 RecyclerView ,暂时没有想到好的方法。不过呢,这样会出现页面在滑动时每次都需要在 onBindView 方法中给每一个 item 设置 Adapter 导致页面在滑动的时候会有点卡顿。

具体的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class CategoryInterestAdapter extends CommonAdapter<CategoryBean> {

public CategoryInterestAdapter( Context context, int layoutId, List<CategoryBean> datas) {
super(context, layoutId, datas);
}

@Override
protected void convert(ViewHolder holder, final CategoryBean categoryBean, int position) {

holder.setText(R.id.tv_category_title, categoryBean.getCategoryTitle());
//获取item view (其实就是 RecyclerView 对象)
RecyclerView recyclerView = holder.getView(R.id.rv_category_list);


final List<CategoryBean.IntereseBean> intereseBeanList = categoryBean.getList();
CategoryItemAdapter adapter;
//适配器绑定到RecyclerView
adapter = new CategoryItemAdapter(recyclerView.getContext(), R.layout.item_category_list_item, intereseBeanList);

recyclerView.setLayoutManager(new GridLayoutManager(recyclerView.getContext(), 5));
recyclerView.setAdapter(adapter);
}

分析卡顿原因

RecyclerView 来说,它内部有一个 ViewHolderRecycler 机制会对每一个 item view 进行缓存操作,而当前的 item view 就是 RecyclerView 了,但是并没有对 RecyclerView 的适配器进行缓存,导致每次回调 onBindView (该方法就是上面的 convert 方法)时都需要进行重新设置新的适配器给 RecyclerView,因此我认为这就是卡顿的地方。

解决卡顿

既然每次在回调 onBindView 方法时都需要给 RecyclerView 设置 Adapter ,并且每一个 RecyclerView 只会绑定一个 Adapter ,可以说是一一对应了,那么就可以使用 WeakHashMap<RecyclerView,Adapter> 来做缓存操作。

外层列表的 RecyclerView 负责对每一个子项 RecyclerView 的视图进行回收缓存操作,而每一个子项的 RecyclerView 的适配器就交给 WeakHashMap<RecyclerView,Adapter> 来做缓存操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class CategoryInterestAdapter extends CommonAdapter<CategoryBean> {
//这里使用 WeakHashMap 作为缓存容器
private WeakHashMap<RecyclerView, RecyclerView.Adapter> adapters = new WeakHashMap<>();


public CategoryInterestAdapter( Context context, int layoutId, List<CategoryBean> datas) {
super(context, layoutId, datas);

}

@Override
protected void convert(ViewHolder holder, final CategoryBean categoryBean, int position) {

holder.setText(R.id.tv_category_title, categoryBean.getCategoryTitle());
//获取item view (其实就是 RecyclerView 对象)
RecyclerView recyclerView = holder.getView(R.id.rv_category_list);


final List<CategoryBean.IntereseBean> intereseBeanList = categoryBean.getList();
CategoryItemAdapter adapter;
if (adapters.get(recyclerView) != null) {
//从缓冲获取对应的适配器
adapter = (CategoryItemAdapter) adapters.get(recyclerView);
//重新给适配器设置数据adapter.setDatas(intereseBeanList);
//这里可以刷新一下适配器
} else {
//当该RecyclerView没有缓存该适配器时,那么创建一个新的适配器绑定到RecyclerView,并缓存
adapter = new CategoryItemAdapter(recyclerView.getContext(), R.layout.item_category_list_item, intereseBeanList);
adapters.put(recyclerView, adapter);
recyclerView.setLayoutManager(new GridLayoutManager(recyclerView.getContext(), 5));
recyclerView.setAdapter(adapter);
}
}

加了 Map 之后,现在页面滑动的时候就不会很卡了,起码流畅很多吧,也许这不是最好的解决方法。

记录一下这个小知识点,以便日后可以优化。

谢谢支持~