version:2.8.5
今天我们来看下 BaseRecyclerViewAdapterHelper 是如何实现多布局的。
首先我们要实现多类型布局,我们的 adapter 不再是继承自 BaseQuickAdapter 类,而是继承自其的子类 BaseMultiItemQuickAdapter。而且数据源类型需要继承自 MultiItemEntity,MultiItemEntity 是一个接口,代码很少:
源码不多:
字段解析:
1、存储我们的布局资源的 ids
private SparseArray layouts;
2、缺省的布局类型值,当使用多布局时,在渲染 viewholder 的时候类型址不是我们配置的类型值中,就会使用这个。
private static final int DEFAULT_VIEW_TYPE = -0xff;
接下来,我们以一个 BaseMultiItemQuickAdapter 的创建过程来分析代码:
之前我们分析了 BaseQuickAdapter 的代码,其执行过程是一样的,我们实现多布局功能的切入口无非是
1、在执行 getItemViewType 时的能够根据我们的数据源返回对应的布局类型值。
2、在 onCreateDefViewHolder 能够正确拿到类型值进行 viewholder 的渲染。
3、我们在 onBindViewHolder 中根据传递给我们的数据源中接口定义的 getItemViewType 方法返回的类型值来确定当前的 viewholder 是什么类型的,需要绑定什么数据。
(注:之前分析了 adapter 的加载数据时的生命周期方法:getItemViewType->onCreateDefViewHolder->onBindViewHolder,如果不大清楚可以看下前面的文章)
所以,我们在 BaseMultiItemQuickAdapter 里面重写了 getDefItemViewType 方法,为什么时重写 getDefItemViewType 方法而不是 getItemViewType 方法呢?这可不是我糊弄你,因为我们在 BaseQuickAdapter 里面重写了 getItemViewType 方法,而在 getItemViewType 方法里调用了 getDefItemViewType 方法来回去类型值,该方法也在之前的分析 BaseQuickAdapter 源码的文章中分析了的。
重写之后做了什么呢?看代码:
@Override
protected int getDefItemViewType(int position) {
Object item = mData.get(position);
if (item instanceof MultiItemEntity) {
return ((MultiItemEntity)item).getItemType();
}
return DEFAULT_VIEW_TYPE;
}
很简单,因为我们的数据源实现了 MultiItemEntity 接口。直接判断该 position 的数据是不是实现了 MultiItemEntity 接口,是调用接口的 getItemType 方法返回类型值,不是返回默认类型值。
第一步返回类型值的代码改造完成了,接下来第二部就是根据类型值渲染 viewholder。BaseMultiItemQuickAdapter 直接重写了 onCreateDefViewHolder 方法来实现该扩展:
@Override
protected K onCreateDefViewHolder(ViewGroup parent, int viewType) {
return createBaseViewHolder(parent, getLayoutId(viewType));
}
代码很简单,从我们存储布局缓存的字段中根据 viewType 返回对象的布局资源的 ids。
所以 BaseMultiItemQuickAdapter 还给我们包装了一个 addItemType 方法:
protected void addItemType(int type, @LayoutRes int layoutResId) {
if (layouts == null) {
layouts = new SparseArray<>();
}
layouts.put(type, layoutResId);
}
该方法很简单,就是将不同的布局资源的 ids 和对应的类型值存储起来。
所以我们的创建多布局的时候,需要的构造函数中调用 addItemType 来添加不同的布局资源
最后一步,绑定数据;一般绑定数据实在 onBindViewHolder 中实现的,而我们的 BaseRecyclerViewAdapterHelper 对其进行了包装,提供了一个 convert 方法,所以我们只需要在 convert 方法中根据数据源数据节点的类型值判断绑定的是那个布局的数据即可。
总结:理解了 adapter 加载数据的生命周期方法的执行顺序很重要(getItemViewType->onCreateDefViewHolder->onBindViewHolder)。
只要控制 viewType 的返回、viewholder 的渲染。viewholder 数据的绑定即可。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于