BaseListAdapter實(shí)現(xiàn)
public abstract class BaseListAdapter<T> extends BaseAdapter
BaseListAdapter是一個(gè)模板類繼承Android SDK中的BaseAdapter或南,里面可以看到一個(gè)成員對(duì)象
private List<T> list = new ArrayList<>();
通過該對(duì)象裝載Adater中所需要的數(shù)據(jù)焊夸,經(jīng)巢氖В看到有朋友在Adapter的外部持有Adapter中l(wèi)ist引用用來改變Adapter中的數(shù)據(jù)磨淌,其實(shí)這樣會(huì)導(dǎo)致兩個(gè)對(duì)象同時(shí)對(duì)Adapter中的數(shù)據(jù)進(jìn)行改變级遭,風(fēng)險(xiǎn)是不可控的望拖,而且外部的list生命周期在長(zhǎng)于Adapter的時(shí)候會(huì)導(dǎo)致list來不及內(nèi)存回收,如果做了一些非法的操作很容易使得list對(duì)象這塊內(nèi)存逃逸出去挫鸽,比如用一個(gè)static的引用去指向它说敏。在Adapter中增加一些數(shù)據(jù)改變的方法可以避免這一切情況的出現(xiàn),而且很方便丢郊。
/**
* 初始化list
*
* @param list
*/
public void initList(List<T> list) {
if (this.list.size() > 0) {
this.list.clear();
}
this.list.addAll(list);
notifyDataSetChanged();
}
/**
* add the list ,but no clear
*
* @param list
*/
public void addList(List<T> list) {
this.list.addAll(list);
notifyDataSetChanged();
}
/**
* clear all list
*/
public void clearList() {
this.list.clear();
notifyDataSetChanged();
}
```
通過這些方法使得`Adapter`才真正成為`data controller`盔沫, 在每次需要數(shù)據(jù)操作的時(shí)候?qū)Adapter`進(jìn)行發(fā)送消息。
下面就是真正源碼抽象的過程了:
##1. 首先是getView()方法的抽象
```java
@Override
public final View getView(int position, View convertView, ViewGroup parent) {
BaseViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = onCreateViewHolder(position, getViewBundles());
convertView = createView(position, viewHolder);
} else {
viewHolder = (BaseViewHolder) convertView.getTag();
}
if (convertView == null || convertView.getTag() == null)
throw new NullPointerException(" creatview fails");
onSetViewHolder(position, getItem(position), viewHolder);
return convertView;
}
```
在`getView`中通過`position`參數(shù)實(shí)例化對(duì)應(yīng)的`viewHolder`對(duì)象`onCreateViewHolder`方法會(huì)call`getItemViewType`方法通過子類實(shí)現(xiàn)的`List<ViewBundle> ViewBundles`對(duì)象取得需要的ViewHolder.class類型然而通過反射去實(shí)例化枫匾。
```java
protected BaseViewHolder onCreateViewHolder(int pos,List<ViewBundle> ViewBundles){
Class<? extends BaseViewHolder> clazz = ViewBundles
.get(getItemViewType(pos)).vHClazz;
return ViewUtil.getInstance(clazz);
}
拿到ViewHolder
對(duì)象后就可以開始進(jìn)行相應(yīng)的數(shù)據(jù)set了架诞,
onSetViewHolder(position, getItem(position), viewHolder);
這個(gè)是set data的方法:
/**
* set data for viewHolder by viewType(through by getItemViewType)
*
* @param position
* @param bean
* @param baseViewHolder
*/
protected void onSetViewHolder(int position, T bean,
BaseViewHolder baseViewHolder) {
baseViewHolder.setView(bean, getContext());
}
在onSetViewHolder方法中可以看到回去調(diào)用ViewHolder父類的setView()方法,下面是BaseViewHolder的代碼干茉,通過baseViewHolder.setView(bean, getContext());
可以調(diào)用子類的具體實(shí)現(xiàn)谴忧,這樣就解耦了adapter和viewHolder之間的關(guān)聯(lián),并且不需要關(guān)注viewHolder的對(duì)象具體類型(因?yàn)樵趃etViewTypeCount!=1的時(shí)候會(huì)在onBindViewHolder(List<ViewBundle> list)
中綁定多個(gè)BaseViewHolder子類的類型)角虫,其實(shí)就是java多態(tài)的使用沾谓。
public static abstract class BaseViewHolder<T> {
public BaseViewHolder() {
}
protected abstract void setView(T bean, Context context);
public Class getClassTag() {
return this.getClass();
}
}
2. ViewBundle的職能?
在子類實(shí)現(xiàn)中有這樣的一個(gè)方法onBindViewHolder(List<ViewBundle> list)
戳鹅,ViewBundle的作用是什么呢均驶?
public static class ViewBundle {
public ViewBundle(int layoutId, Class<? extends BaseViewHolder> clazz) {
this.layoutId = layoutId;
this.vHClazz = clazz;
}
public Class<? extends BaseViewHolder> vHClazz;
public int layoutId;
@Override
public String toString() {
return "ViewBundle{" + "vHClazz=" + vHClazz + ", layoutId="
+ layoutId + '}';
}
}
可以看到其實(shí)是一個(gè)layoutId和viewHolder類型的對(duì)應(yīng)關(guān)系,通過list將數(shù)組對(duì)象傳遞給父類枫虏,通過下標(biāo)取得對(duì)應(yīng)的class值妇穴。
到這里代碼解析全部完畢爬虱,主要工作就是Adapter的簡(jiǎn)單定制,讓子類的具體實(shí)現(xiàn)最小化伟骨。這樣的處理在開發(fā)中可以減少相應(yīng)的繁瑣重復(fù)工作并降低錯(cuò)誤率饮潦,父類中輸出了輸出了必要的log并在子類實(shí)現(xiàn)除錯(cuò)的情況跑出了對(duì)應(yīng)的異常,可以很快的定位原因携狭。
有問題請(qǐng)聯(lián)系我:ganquan3640@gmail.com继蜡。