BaseRecyclerViewAdapterHelper開源項(xiàng)目之BaseMultiItemQuickAdapter 實(shí)現(xiàn)多類型源碼學(xué)習(xí)

更多分享:http://cherylgood.cn

version:2.8.5

今天我們來看下BaseRecyclerViewAdapterHelper是如何實(shí)現(xiàn)多布局的。

首先我們要實(shí)現(xiàn)多類型布局,我們的adapter不再是繼承自BaseQuickAdapter類,而是繼承自其的子類

BaseMultiItemQuickAdapter。而且數(shù)據(jù)源類型需要繼承自MultiItemEntity,

MultiItemEntity是一個(gè)接口,代碼很少:

package com.chad.library.adapter.base.entity;

/**

* https://github.com/CymChad/BaseRecyclerViewAdapterHelper

*/

public interface MultiItemEntity {

int getItemType();

}

其主要用意是我們的數(shù)據(jù)源繼承MultiItemEntity,這樣子,我們可以在數(shù)據(jù)源中動(dòng)態(tài)的返回一個(gè)int類型的數(shù)值(代表某一類型的item),大家可以想一下,我們?cè)阡秩緑iewholder的時(shí)候,如果想實(shí)現(xiàn)多類型的viewholder,而viewholder的類型展示又跟所需綁定的數(shù)據(jù)息息相關(guān),那么如果我們?cè)跀?shù)據(jù)源中提供一種確定viewholder類型的能力,理論上是不是就可以達(dá)到我們要的效果了?我們帶著這樣的一個(gè)假設(shè)繼續(xù)往下看。

而這個(gè)BaseMultiItemQuickAdapter 是何許人也,是如何實(shí)現(xiàn)多類型布局的呢?我們來看下源碼:

package com.chad.library.adapter.base;

import android.support.annotation.LayoutRes;

import android.util.SparseArray;

import android.view.ViewGroup;

import com.chad.library.adapter.base.entity.MultiItemEntity;

import java.util.List;

/**

* https://github.com/CymChad/BaseRecyclerViewAdapterHelper

*/

public abstract class BaseMultiItemQuickAdapter extends BaseQuickAdapter {

/**

* layouts indexed with their types

*/

private SparseArray layouts;

private static final int DEFAULT_VIEW_TYPE = -0xff;

/**

* Same as QuickAdapter#QuickAdapter(Context,int) but with

* some initialization data.

*

* @param data? ? A new list is created out of this one to avoid mutable list

*/

public BaseMultiItemQuickAdapter( List data) {

super( data);

}

@Override

protected int getDefItemViewType(int position) {

Object item = mData.get(position);

if (item instanceof MultiItemEntity) {

return ((MultiItemEntity)item).getItemType();

}

return DEFAULT_VIEW_TYPE;

}

protected void setDefaultViewTypeLayout(@LayoutRes int layoutResId) {

addItemType(DEFAULT_VIEW_TYPE, layoutResId);

}

@Override

protected K onCreateDefViewHolder(ViewGroup parent, int viewType) {

return createBaseViewHolder(parent, getLayoutId(viewType));

}

private int getLayoutId(int viewType) {

return layouts.get(viewType);

}

protected void addItemType(int type, @LayoutRes int layoutResId) {

if (layouts == null) {

layouts = new SparseArray<>();

}

layouts.put(type, layoutResId);

}

}

源碼不多:

字段解析:

1、存儲(chǔ)我們的布局資源的ids

private SparseArray layouts;

2、缺省的布局類型值,當(dāng)使用多布局時(shí),在渲染viewholder的時(shí)候類型址不是我們配置的類型值中,就會(huì)使用這個(gè)。

private static final int DEFAULT_VIEW_TYPE = -0xff;

接下來,我們以一個(gè)BaseMultiItemQuickAdapter的創(chuàng)建過程來分析代碼:

之前我們分析了BaseQuickAdapter的代碼,其執(zhí)行過程是一樣的,我們實(shí)現(xiàn)多布局功能的切入口無非是

1、在執(zhí)行g(shù)etItemViewType時(shí)的能夠根據(jù)我們的數(shù)據(jù)源返回對(duì)應(yīng)的布局類型值。

2、在onCreateDefViewHolder 能夠正確拿到類型值進(jìn)行viewholder的渲染。

3、我們?cè)趏nBindViewHolder中根據(jù)傳遞給我們的數(shù)據(jù)源中接口定義的getItemViewType方法返回的類型值來確定當(dāng)前的viewholder是什么類型的,需要綁定什么數(shù)據(jù)。

(注:之前分析了adapter的加載數(shù)據(jù)時(shí)的生命周期方法:getItemViewType->onCreateDefViewHolder->onBindViewHolder,如果不大清楚可以看下前面的文章)

所以,我們?cè)贐aseMultiItemQuickAdapter 里面重寫了getDefItemViewType方法,為什么時(shí)重寫

getDefItemViewType方法而不是getItemViewType方法呢?這可不是我糊弄你,因?yàn)槲覀冊(cè)贐aseQuickAdapter里面重寫了getItemViewType方法,而在getItemViewType方法里調(diào)用了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;

}

很簡(jiǎn)單,因?yàn)槲覀兊臄?shù)據(jù)源實(shí)現(xiàn)了MultiItemEntity接口。直接判斷該position的數(shù)據(jù)是不是實(shí)現(xiàn)了

MultiItemEntity接口,是調(diào)用接口的getItemType方法返回類型值,不是返回默認(rèn)類型值。

第一步返回類型值的代碼改造完成了,接下來第二部就是根據(jù)類型值渲染viewholder。

BaseMultiItemQuickAdapter直接重寫了onCreateDefViewHolder 方法來實(shí)現(xiàn)該擴(kuò)展:

@Override

protected K onCreateDefViewHolder(ViewGroup parent, int viewType) {

return createBaseViewHolder(parent, getLayoutId(viewType));

}

代碼很簡(jiǎn)單,從我們存儲(chǔ)布局緩存的字段中根據(jù)viewType返回對(duì)象的布局資源的ids。

所以BaseMultiItemQuickAdapter 還給我們包裝了一個(gè)addItemType方法:

protected void addItemType(int type, @LayoutRes int layoutResId) {

if (layouts == null) {

layouts = new SparseArray<>();

}

layouts.put(type, layoutResId);

}

該方法很簡(jiǎn)單,就是將不同的布局資源的ids和對(duì)應(yīng)的類型值存儲(chǔ)起來。

所以我們的創(chuàng)建多布局的時(shí)候,需要的構(gòu)造函數(shù)中調(diào)用addItemType來添加不同的布局資源

最后一步,綁定數(shù)據(jù);一般綁定數(shù)據(jù)實(shí)在onBindViewHolder中實(shí)現(xiàn)的,而我們的BaseRecyclerViewAdapterHelper對(duì)其進(jìn)行了包裝,提供了一個(gè)convert方法,所以我們只需要的

convert方法中根據(jù)數(shù)據(jù)源數(shù)據(jù)節(jié)點(diǎn)的類型值判斷綁定的是那個(gè)布局的數(shù)據(jù)即可。

總結(jié):理解了adapter加載數(shù)據(jù)的生命周期方法的執(zhí)行順序很重要(getItemViewType->onCreateDefViewHolder->onBindViewHolder)。

只要控制viewType的返回、viewholder的渲染。viewholder數(shù)據(jù)的綁定即可。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容