非約束列表(萬能適配器) v4.0 重磅升級
請移步:
http://www.reibang.com/p/e9558141fb5f
v3.1更新
- 完善更多下拉刷新場景
- 增加【上拉分頁加載】和【無感分頁加載】
v3.0更新
- 增加超強功能的下拉刷新
v2.0更新
- 增加對團(tuán)隊開發(fā)的支持
- 增加對混合列表的支持
簡介
非約束列表洒沦,
也是很多同學(xué)口中的“萬能適配器”万搔,
不過我并不認(rèn)同“萬能”的這個說法律适,
誰的適配器ListView和RecyclerView通用刹勃?
預(yù)覽一下效果先:
1贼涩、單列列表
2、多列列表
3脓规、混合列表
顯然链快,
從界面上看不出什么名堂,
那就先說下我的非約束列表有什么優(yōu)勢吧微猖。
打個比方谈息,
某中學(xué)要給10臺電腦升級程序,
平均一臺電腦操作一次需要一個小時凛剥。
初中生可能會操作10次黎茎,
耗時10小時。
高中生可能會把所有電腦連起來当悔,
同時操控傅瞻,
只需要操作一次踢代,
耗時一個小時。
我們用普通的Adapter的話嗅骄,
就好比初中生胳挎,
每次修改一個條目,
就把所有使用這個條目的類全改一遍溺森,
無論是Activity還是Adapter慕爬,
但是用了非約束列表就不一樣了,
邏輯基本上都在Bean里屏积,
基本上只需要改itemLayout的樣式医窿,
和Bean里的邏輯即可。
到這里炊林,
可能有同學(xué)會疑惑姥卢,
為什么不管Adapter?
因為渣聚,
我的項目只需要一個Adapter独榴,
一個Adapter,
全場通用奕枝!
說得細(xì)一點棺榔,
就是我把邏輯全部拆散重組,
Adapter架空隘道,
只負(fù)責(zé)Activity症歇、ViewHolder、bean之間的連通谭梗。
我個人喜歡把View和與其相對應(yīng)的數(shù)據(jù)放一起当船,
所以我把ViewHolder和邏輯放到了Bean里,
通過一個接口來使兩者進(jìn)行結(jié)合默辨,
哦不,
是將數(shù)據(jù)顯示到View上苍息。
但是缩幸,
ViewHolder那么多,
Adapter怎么將其連通起來呢竞思?
所以我寫了一個ViewHolderManager表谊,
ViewHolderManager負(fù)責(zé)根據(jù)條目的類型,
找到相對應(yīng)的ViewHolder盖喷,
進(jìn)行實例化并返回給Adapter爆办。
整體流程如下圖:
好了,
原理就說到這里课梳,
━━━━━━━━━━━這是清理內(nèi)存的分割線━━━━━━━━━━━
下面開始聊聊我的非約束列表的使用步驟:
一:
新建一個Bean類距辆,
里邊寫個ViewHolder內(nèi)部類余佃,
繼承ViewHolderManager.ViewHolder,
和普通的Adapter的內(nèi)部類差不多跨算,
不過需要注意的是爆土,
構(gòu)造里的參數(shù)不一樣:
/**
* ViewHolder --> 主頁的按鈕
*/
public static class MusicViewHolder extends ViewHolderManager.ViewHolder {
public RelativeLayout rl_music;
public TextView tv_song;
public TextView tv_singer;
public MusicViewHolder(ViewGroup viewGroup) {
// 兩個參數(shù),第一個viewGroup不解釋诸蚕,第二個即本ViewHolder對應(yīng)的LayoutXml
super(viewGroup, R.layout.item_music);
rl_music = (RelativeLayout) itemView.findViewById(R.id.rl_music);
tv_song = (TextView) itemView.findViewById(R.id.tv_song);
tv_singer = (TextView) itemView.findViewById(R.id.tv_singer);
}
}
不難發(fā)現(xiàn)步势,
構(gòu)造里多了個參數(shù),
即該ViewHolder對應(yīng)的LayoutXml.
二:
進(jìn)入ViewHolderManager背犯,
對應(yīng)你新寫的ViewHolder坏瘩,
增加一個公開靜態(tài)常量,
只要不與其他的值重復(fù)即可漠魏,
并put到itemMap里倔矾,
key為你剛寫的常量,
value為剛寫的ViewHolder的class蛉幸。
/**
* 條目類型 --> ……
*/
public static final int //……
/**
* 條目類型 --> 新聞卡片
*/
public static final int ITEM_TYPE_NEWS = 8;
/**
* 條目類型 --> 音樂
*/
public static final int ITEM_TYPE_MUSIC = 9;
/**
* 加載條目類型破讨,以及對應(yīng)的條目XML
*/
static {
itemMap = new HashMap<>();
……
itemMap.put(ITEM_TYPE_NEWS, BeanNews.NewsViewHolder.class);
itemMap.put(ITEM_TYPE_MUSIC, BeanMusic.MusicViewHolder.class);
}
三:
回到剛才寫的Bean,
繼承FreedomBean奕纫,
在initItemType()里提陶,
set一下剛在ViewHolderManager里定義的那個常量,
@Override
protected void initItemType() {
setItemType(ViewHolderManager.ITEM_TYPE_MUSIC);
}
在initBindView()里匹层,
把普通Adapter里onBindViewHolder()的代碼挪過來隙笆。
@Override
protected void initBindView(final List list) {
setViewHolderBindListener(new ViewHolderBindListener() {
@Override
public void onBindViewHolder(final Activity activity, final ViewHolderManager.ViewHolder viewHolder, final int position) {
final MusicViewHolder vh = (MusicViewHolder) viewHolder;
final BeanMusic bean = (BeanMusic) list.get(position);
vh.tv_song.setText(bean.getSong());
vh.tv_singer.setText(bean.getSinger());
vh.rl_music.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
……
}
});
}
});
}
如果需要和Activity交互,
則Activity實現(xiàn)FreedomCallback接口升筏,
并在onClickCallback里編寫代碼撑柔,
然后回到Bean里調(diào)用getCallback(activity).onClickCallback();
vh.rl_music.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 點擊事件
// 如果不需要和Activity進(jìn)行交互,
// 那么直接在這里寫點擊事件即可
//
// 如果需要和Activity進(jìn)行交互您访,
// 那么Activity實現(xiàn)FreedomCallback接口铅忿,
// 并在onClickCallback里編寫代碼,
// 即可觸發(fā)回調(diào)灵汪,
// 以和Activity進(jìn)行交互檀训。
//
// 注意:
// 該Activity必須實現(xiàn)FreedomCallback接口才能觸發(fā)回調(diào),
// 否則會報錯
getCallback(activity).onClickCallback(v, position, vh);
}
});
例:
類BeanMusic里initBindView方法里的vh.rl_music.setOnClickListener()享言。
好了峻凫,
Bean就完成了,
Activity里使用它的方式和普通的沒什么差別览露,
只是聲明數(shù)據(jù)源mList的時候荧琼,
類型為Object或者不要加類型就好:
/**
* 數(shù)據(jù)源
*/
private List mList;
然后就可以使用FreedomAdapter了:
// 實例化RecyclerView
mAdapter = new FreedomAdapter(this, mList);
recycler.setLayoutManager(new LinearLayoutManager(this));
recycler.setItemAnimator(new DefaultItemAnimator());
recycler.setAdapter(mAdapter);
使用起來雖然沒有比普通的簡單太多,
但也功能要比普通的強大太多啊不是么?
本文github鏈接:
https://github.com/Bamboy120315/Freedom