轉(zhuǎn)載請標明出處:
http://www.reibang.com/p/5ad655759c28
本文出自:【張旭童的簡書】 (http://www.reibang.com/users/8e91ff99b072/latest_articles)
代碼傳送門:喜歡的話函筋,隨手點個star。多謝
https://github.com/mcxtzhang/all-base-adapter
概述
開發(fā)中,經(jīng)常會用到動態(tài)在ScrollView、LinearLayout里addView的事馋艺,尤其是ItemView一樣時,每次都要寫一大堆代碼 inflater 動態(tài)addView迈套,很煩捐祠。
還有就是在嵌套ListView、ScrollView時桑李,想采用LinearLayout替代(這樣性能更佳踱蛀,不明白的看一個控件搞定嵌套ListView)窿给,但動態(tài)addView步驟神煩。
這個時候就開始期待率拒,能不能有一種快速為任意ViewGroup添加子View的東西崩泡。
我之前為此事特意寫過一篇LinearLayout封裝博文,封裝了一個控件使用猬膨。試圖一個控件搞定嵌套ListView角撞。但是后來發(fā)現(xiàn),采用繼承某個ViewGroup做這個事情不夠優(yōu)雅 寥掐,對代碼有侵入性靴寂,如果有其他ViewGroup需要動態(tài)addView,就會寫重復的代碼 召耘。
前幾天有人在群里問百炬,如何方便的給ScrollView動態(tài)添加不同種類型的childView,類似RecyclerView那樣污它。我之前的封裝由于內(nèi)部有一個簡單的重用機制剖踊,只支持單一ItemType,也不支持多種類型的childView衫贬。
那么需求就來了:
- 快速簡單使用
- 支持任意ViewGroup
- 無耦合
- 無侵入性
- Item支持多種類型
除此之外德澈,我還加入:
- 為ItemView設置
OnItemClickListener
- 為ItemView設置
OnItemLongClickListener
本文就封裝了這么一個東西。
核心:
- 利用Adapter模式封裝getView的操作
- 搭配一個工具類固惯,為所有ViewGroup addView梆造。
- 再封裝出兩個使用快速簡單的Adapter 分別用于添加 單一Item布局、多種Item布局葬毫。
PS:所以本文也算是填了之前的一個坑镇辉,在之前適配器模式博文文末,我就提到要寫一篇為流式布局增加Adapter的文章贴捡,作為Adapter的實戰(zhàn)演練忽肛。使用本文封裝的Adapter自然可以達到這一點。
由于采用Adapter隔離ViewGroup和ItemView烂斋,在切換ViewGroup時屹逛,十分方便。
如:在需求讓你把一個HorizontalScrollView包裹的水平標簽轉(zhuǎn)換成流式布局時汛骂,只需要在xml替換控件即可罕模。Adapter將自動完成適配的工作。其他代碼一句不用修改香缺。
不BB了手销,先看看以后如何使用吧,夠不夠簡單粗暴图张。
使用預覽
單一Item類型:
Adapter泛型傳入JavaBean锋拖,構造函數(shù)傳入數(shù)據(jù)集和layout布局诈悍,一句代碼搞定:
//單一ItemView
ViewGroupUtils.addViews(mLinearLayout, new SingleAdapter<TestBean>(this, mDatas, R.layout.item_test) {
@Override
public void onBindView(ViewGroup parent, View itemView, TestBean data, int pos) {
Glide.with(LinearLayoutActivity.this)
.load(data.getAvatar())
.into((ImageView) itemView.findViewById(R.id.ivAvatar));
((TextView) itemView.findViewById(R.id.tvName)).setText(data.getName());
}
});
效果:
以前會用ScrollView嵌套ListView,現(xiàn)在只要用ScrollView套LinearLayout即可兽埃,性能更佳侥钳。
多種Item類型:
多種Item類型分兩種情況:
數(shù)據(jù)結構相同:
數(shù)據(jù)結構相同依然可以給Adapter傳入泛型,避免強轉(zhuǎn):
//多種ItemViewType柄错,但是數(shù)據(jù)結構相同舷夺,可以傳入數(shù)據(jù)結構泛型,避免強轉(zhuǎn)
ViewGroupUtils.addViews(linearLayout, new MulTypeAdapter<MulTypeBean>(this, initDatas()) {
@Override
public void onBindView(ViewGroup parent, View itemView, MulTypeBean data, int pos) {
((TextView) itemView.findViewById(R.id.tvWords)).setText(data.getName() + "");
Glide.with(MulTypeActivity.this)
.load(data.getAvatar())
.into((ImageView) itemView.findViewById(ivAvatar));
}
});
效果:
數(shù)據(jù)結構不同:
如果數(shù)據(jù)結構不同敢伸,則不用傳入泛型,但是使用時需要強轉(zhuǎn):
//多種Item類型:數(shù)據(jù)結構不同 不傳泛型了 使用時需要強轉(zhuǎn)javaBean恒削,判斷ItemLayoutId
ViewGroupUtils.addViews((ViewGroup) findViewById(R.id.activity_mul_type_mul_bean), new MulTypeAdapter(this, datas) {
@Override
public void onBindView(ViewGroup parent, View itemView, IMulTypeHelper data, int pos) {
switch (data.getItemLayoutId()) {
case R.layout.item_mulbean_1:
MulBean1 mulBean1 = (MulBean1) data;
Glide.with(MulTypeMulBeanActivity.this)
.load(mulBean1.getUrl())
.into((ImageView) itemView);
break;
case R.layout.item_mulbean_2:
MulBean2 mulBean2 = (MulBean2) data;
TextView tv = (TextView) itemView;
tv.setText(mulBean2.getName());
}
}
});
數(shù)據(jù)結構:
public class MulBean1 implements IMulTypeHelper {
private String url;
@Override
public int getItemLayoutId() {
return R.layout.item_mulbean_1;
}
}
public class MulBean2 implements IMulTypeHelper {
private String name;
@Override
public int getItemLayoutId() {
return R.layout.item_mulbean_2;
}
}
Item1布局是一個ImageView池颈,Item2布局是一個TextView
效果:
Item點擊事件
item的點擊和長按等事件携丁,有兩種方法設置,這里以點擊事件為例琢歇,長按事件同理:
Adapter.onBindView()里設置
在Adapter.onBindView()
方法里能拿到ItemView,自然就可以設置各種事件梦鉴。類似RecyclerView矿微。
在這里設置優(yōu)先級更高。原因后文會提到尚揣。
@Override
public void onBindView(ViewGroup parent, View itemView, final MulTypeBean data, int pos) {
....
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(mContext, "onBindView里設置:文字是:" + data.getName(), Toast.LENGTH_SHORT).show();
}
});
}
通過ViewGroupUtils設置
可以在ViewGroupUtils.addViews
直接作為參數(shù)傳入.
也可以用ViewGroupUtils.setOnItemClickListener()
設置 。
優(yōu)先級比Adapter.onBindView()
里設置低掖举,原因后文會提到快骗。
//設置OnItemClickListener
OnItemClickListener onItemClickListener = new OnItemClickListener() {
@Override
public void onItemClick(ViewGroup parent, View itemView, int position) {
Toast.makeText(MulTypeActivity.this, "通過OnItemClickListener設置:" + position, Toast.LENGTH_SHORT).show();
}
};
//可以在`ViewGroupUtils.addViews`直接作為參數(shù)傳入.\
ViewGroupUtils.addViews(linearLayout, adapter ,onItemClickListener);
//或者 也可以用`ViewGroupUtils.setOnItemClickListener()`設置
ViewGroupUtils.setOnItemClickListener(linearLayout,onItemClickListener);
看起來還是挺好的,嗯~至少我自己這么覺得塔次,我個人比較喜歡這種0耦合方篮,每一個庫都像可組裝拆卸的機關槍一樣,拿起來就用励负。而不是笨重功能繁多的重裝坦克藕溅。
搭配我的得意之作,每次必安利的史上集成最簡單側滑菜單控件继榆。
效果如下:
無特殊設置,僅僅替換ViewGroup為流式布局集币,替換Item根布局為我擼的側滑菜單庫考阱,能感受到這種0耦合的庫的魅力了么。23333333 鞠苟。
設計思路
下面就讓我手摸手帶大家實現(xiàn)它乞榨。
先看類圖。
UML類圖:
先簡要概括
我們的頂層接口
IViewGroupAdapter
暴露出兩個方法供ViewGroup使用当娱。ViewGroupUtils
是為任意ViewGroup 動態(tài)addView的工具類吃既,只依賴于IViewGroupAdapter
接口即可完成工作。BaseAdapter
是第二層跨细,在這一層引入了數(shù)據(jù)集鹦倚,用List<T>
保存。實現(xiàn)IViewGroupAdapter
的方法,重載一個三參數(shù)的getView()
方法扼鞋,供子類去實現(xiàn)申鱼。SingleAdapter
是第三層,一個簡化的Adapter,只支持單種Item,以LayoutId 構建View。實現(xiàn)getView()
方法云头,并暴露出onBindView()
供用戶快速使用捐友。MulTypeAdapter
也同處第三層,一個支持多種Item的Adapter溃槐。依賴IMulTypeHelper
接口匣砖,利用其getItemLayoutId()
方法去實現(xiàn)getView()
方法,并暴露出onBindView()
供用戶快速使用昏滴。
頂層接口設計
頂層接口猴鲫,即IViewGroupAdapter
。
根據(jù)迪米特法則(最少知道原則),我們應該抽象出一個頂層的接口谣殊,對ViewGroup暴露出最少的方法供使用拂共。
我們想一下,對于ViewGroup姻几,它最少只需要哪些就能完成我們的需求宜狐。
- ChildView是什么---> View
- 有多少ChildView 需要 添加--->count
所以,我們的最頂層接口如下編寫:
public interface IViewGroupAdapter {
/**
* ViewGroup調(diào)用獲取ItemView
*
* @param parent
* @param pos
* @return
*/
View getView(ViewGroup parent, int pos);
/**
* ViewGroup調(diào)用蛇捌,得到ItemCount
*
* @return
*/
int getCount();
}
ok抚恒,代碼寫到這里,后面的我們暫且不提络拌,我們就可以寫動態(tài)addView的工具類了俭驮。因為我們的ViewGroup依賴的所有信息都由IViewGroupAdapter
這個接口提供了。
工具類
ViewGroupUtils
是為任意ViewGroup 動態(tài)addView的工具類春贸,不考慮點擊事件的情況下混萝,只依賴于 IViewGroupAdapter
接口即可完成工作遗遵。
如下編寫:
/**
* 為任意ViewGroup 添加ItemViews.
*
* @param viewGroup 必傳
* @param adapter 必傳,至少提供要add的View和需要add的count
* @param removeViews 是否需要remove掉之前的Views
*/
public static void addViews(final ViewGroup viewGroup, IViewGroupAdapter adapter
, boolean removeViews) {
if (viewGroup == null || adapter == null) {
return;
}
//如果需要remove掉之前的Views
if (removeViews && viewGroup.getChildCount() > 0) {
viewGroup.removeAllViews();
}
//開始添加子Views,通過Adapter獲得需要添加的Count
int count = adapter.getCount();
for (int i = 0; i < count; i++) {
//通過Adapter獲得ItemView
View itemView = adapter.getView(viewGroup, i);
viewGroup.addView(itemView);
}
}
如此即可完成 動態(tài)給任意ViewGroup addView 的工作譬圣。
不過我們開頭提過瓮恭,我還是想引入ItemView的點擊和長按事件的。但是關于這兩個ItemListener厘熟,還是有一些東西要考慮的屯蹦。
ItemListener的設計
為ViewGroup提供OnItemClickListener
,有個問題需要考慮:
如果使用者調(diào)用了setOnItemClickListener
绳姨,且在Adapter
里自己又對ItemView
設置了OnClickListener
登澜,那么究竟該觸發(fā)哪個Listener
,即它們的優(yōu)先級飘庄。
我們不應該自己靠腦子想答案脑蠕,還是參照系統(tǒng)原有的設計比較好。既然ListView提供了OnItemClickListener
跪削,那么我們參照它的設計來就行谴仙。
先說結論:通過參照ListView的源碼,以及實驗得知碾盐,對ItemView
的OnClickListener
優(yōu)先級 > ViewGroup的OnItemClickListener
晃跺。
為什么?答案在源碼中毫玖,感興趣看掀虎,不感興趣直接跳過。
從AbsListView的onTouchEvent()
->onTouchUp()
->PerformClick
->performItemClick
-> AdapterView.performItemClick()
-> AdapterView.mOnItemClickListener
付枫,即可找到答案烹玉。
這里不詳細分析源碼,不是本文重點阐滩,簡單的說二打,從入口處是AbsListView的onTouchEvent()
,我們可以知道,ListView本身并沒有干預ItemView
的點擊事件(即沒有為其設置OnClickListener
)掂榔,是在ItemView
不消耗Touch事件時 才進行Item點擊事件的觸發(fā)址儒。
因此若ItemView
設置了OnClickListener
,AbsListView的onTouchEvent()
將收不到MotionEvent.ACTION_UP
事件衅疙,因而也不會觸發(fā)OnItemClickListener
。所以這決定了ItemView
的OnClickListener
優(yōu)先級高鸳慈。
還有一個問題饱溢,我們可以通過View.hasOnClickListeners()
這個方法來判斷View是否設置了OnClickListener
,但是這個方法在API15才加入走芋,為了能兼容低版本欲逃,我采用了另一種方法判斷刹泄,itemView.isClickable()
女揭,如果true,我當做有點擊事件溉仑,如果false,我當做沒有状植。
其實在ListView中這個問題也是一樣的浊竟,itemView.isClickable()
為true的話,點擊事件就被攔截住津畸,不會分發(fā)至AbsListView的onTouchEvent()
里了振定。所以我們這么寫是沒問題,并且是正確的肉拓。
ItemListener的完整實現(xiàn):
既然如此后频,那么我們在程序中,應該如下編寫:
for (int i = 0; i < count; i++) {
View itemView = adapter.getView(viewGroup, i);
viewGroup.addView(itemView);
//添加點擊事件
if (null != onItemClickListener && !itemView.isClickable()) {
final int finalI = i;
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemClickListener.onItemClick(viewGroup, view, finalI);
}
});
}
//添加點擊事件
if (null != onItemLongClickListener && !itemView.isLongClickable()) {
final int finalI = i;
itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
return onItemLongClickListener.onItemLongClick(viewGroup, view, finalI);
}
});
}
}
所以完整的addViews()
如下:
/**
* 為任意ViewGroup 添加ItemViews.
*
* @param viewGroup 必傳
* @param adapter 必傳暖途,至少提供要add的View和需要add的count
* @param removeViews 是否需要remove掉之前的Views
* @param onItemClickListener Item點擊事件
* @param onItemLongClickListener Item長按事件
*/
public static void addViews(final ViewGroup viewGroup, IViewGroupAdapter adapter
, boolean removeViews
, final OnItemClickListener onItemClickListener
, final OnItemLongClickListener onItemLongClickListener) {
if (viewGroup == null || adapter == null) {
return;
}
//如果需要remove掉之前的Views
if (removeViews && viewGroup.getChildCount() > 0) {
viewGroup.removeAllViews();
}
//開始添加子Views,通過Adapter獲得需要添加的Count
int count = adapter.getCount();
for (int i = 0; i < count; i++) {
//通過Adapter獲得ItemView
View itemView = adapter.getView(viewGroup, i);
viewGroup.addView(itemView);
//添加點擊事件,itemView之前沒有點擊事件才會去設置
if (null != onItemClickListener && !itemView.isClickable()) {
final int finalI = i;
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemClickListener.onItemClick(viewGroup, view, finalI);
}
});
}
//添加長按事件itemView之前沒有長按事件才會去設置
if (null != onItemLongClickListener && !itemView.isLongClickable()) {
final int finalI = i;
itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
return onItemLongClickListener.onItemLongClick(viewGroup, view, finalI);
}
});
}
}
}
實際中卑惜,我們可能不需要設置Listener,為了快速使用驻售,我又提供了兩個重載方法:
/**
* 為任意ViewGroup 添加ItemViews.
* 并且會清除掉之前所有add過的View
*
* @param viewGroup 必傳
* @param adapter 必傳露久,至少提供要add的View和需要add的count
*/
public static void addViews(final ViewGroup viewGroup, IViewGroupAdapter adapter) {
addViews(viewGroup, adapter, true, null, null);
}
/**
* 為任意ViewGroup 添加ItemViews.
* 并且會清除掉之前所有add過的View
*
* @param viewGroup 必傳
* @param adapter 必傳,至少提供要add的View和需要add的count
* @param onItemClickListener Item點擊事件
*/
public static void addViews(final ViewGroup viewGroup, IViewGroupAdapter adapter
, final OnItemClickListener onItemClickListener) {
addViews(viewGroup, adapter, true, onItemClickListener, null);
}
若不在addViews()
里設置ItemListener芋浮,也可以通過setOnItemClickListener()
和setOnItemLongClickListener()
設置抱环,不過這兩個方法必須在addViews()方法之后調(diào)用:
/**
* 為任意ViewGroup設置OnItemClickListener.
* 該方法必須在addViews()方法之后調(diào)用,否則無效纸巷。
* 因為ItemView 必須被添加在ViewGroup里才能遍歷到镇草。
* 建議直接在addViews()方法里傳入OnItemClickListener進行設置,性能更高
*
* @param viewGroup
* @param onItemClickListener
*/
public static void setOnItemClickListener(final ViewGroup viewGroup, final OnItemClickListener onItemClickListener) {
if (viewGroup == null || onItemClickListener == null) {
return;
}
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
final View itemView = viewGroup.getChildAt(i);
//itemView之前沒有點擊事件才會去設置
if (null != itemView && !itemView.isClickable()) {
final int finalI = i;
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemClickListener.onItemClick(viewGroup, itemView, finalI);
}
});
}
}
}
/**
* 為任意ViewGroup設置OnItemLongClickListener.
* 該方法必須在addViews()方法之后調(diào)用瘤旨,否則無效梯啤。
* 因為ItemView 必須被添加在ViewGroup里才能遍歷到。
* 建議直接在addViews()方法里傳入OnItemLongClickListener進行設置存哲,性能更高
*
* @param viewGroup
* @param onItemLongClickListener
*/
public static void setOnItemLongClickListener(final ViewGroup viewGroup, final OnItemLongClickListener onItemLongClickListener) {
if (viewGroup == null || onItemLongClickListener == null) {
return;
}
int childCount = viewGroup.getChildCount();
for (int i = 0; i < childCount; i++) {
final View itemView = viewGroup.getChildAt(i);
//itemView之前沒有長按事件才會去設置
if (null != itemView && !itemView.isLongClickable()) {
final int finalI = i;
itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
return onItemLongClickListener.onItemLongClick(viewGroup, itemView, finalI);
}
});
}
}
}
Adapter
終于到了我們的重頭戲因宇,Adapter。
BaseAdapter
BaseAdapter
是第二層祟偷,在這一層引入了數(shù)據(jù)集察滑,用List<T>
保存。實現(xiàn)IViewGroupAdapter
的方法,重載一個三參數(shù)的getView()
方法修肠,供子類去實現(xiàn)贺辰。
它和我們平時寫的ListView、RecyclerView的Adapter就比較像了,我也是參照平時的寫法饲化。
核心就是實現(xiàn)IViewGroupAdapter
的getView(ViewGroup parent, int pos)
方法,增加一個數(shù)據(jù)莽鸭,工作轉(zhuǎn)交給三參數(shù)的getView(ViewGroup parent, int pos, T data)
方法。
子類應該 實現(xiàn) getView(ViewGroup parent, int pos, T data)
方法吃靠,在其中inflate or new 出 ItemView硫眨,并綁定數(shù)據(jù)。
public abstract class BaseAdapter<T> implements IViewGroupAdapter {
protected List<T> mDatas;
protected Context mContext;
protected LayoutInflater mInflater;
/**
* ViewGroup調(diào)用獲取ItemView,create bind一起做
*
* @param parent
* @param pos
* @return
*/
@Override
public View getView(ViewGroup parent, int pos) {
return getView(parent, pos, mDatas.get(pos));
}
/**
* 實際的createItemView的地方
*
* @param parent
* @param pos
* @param data
* @return
*/
public abstract View getView(ViewGroup parent, int pos, T data);
/**
* ViewGroup調(diào)用巢块,得到ItemCount
*
* @return
*/
@Override
public int getCount() {
return mDatas != null ? mDatas.size() : 0;
}
}
SingleAdapter
SingleAdapter
是第三層,一個簡化的Adapter,只支持單種Item,以LayoutId 構建View礁阁。實現(xiàn)getView()
方法,并暴露出onBindView()
供用戶快速使用夕冲。
使用時氮兵,一般將數(shù)據(jù)結構的泛型傳入,配合構造函數(shù)傳入的ItemLayoutId使用歹鱼。
它繼承自BaseAdapter
,所以它了實現(xiàn)getView(ViewGroup parent, int pos, T data)
方法泣栈。在根據(jù)傳入的itemLayoutId inflate出ItemView后,會回調(diào)onBindView(ViewGroup parent, View itemView, T data, int pos)
方法弥姻,并返回ItemView供ViewGroup使用南片。
在onBindView(ViewGroup parent, View itemView, T data, int pos)
方法里,我們完成數(shù)據(jù)綁定的工作庭敦。例如加載圖片疼进,也可以設置點擊事件。
public abstract class SingleAdapter<T> extends BaseAdapter<T> {
private int mItemLayoutId;
@Override
public View getView(ViewGroup parent, int pos, T data) {
//實現(xiàn)getView
View itemView = /*onCreateView(parent, pos)*/mInflater.inflate(mItemLayoutId, parent, false);
onBindView(parent, itemView, data, pos);
return itemView;
}
/**
* 暴漏這個 讓外部bind數(shù)據(jù)
*
* @param parent
* @param itemView
* @param data
* @param pos
*/
public abstract void onBindView(ViewGroup parent, View itemView, T data, int pos);
}
MulTypeAdapter
MulTypeAdapter
也同處第三層秧廉,一個支持多種Item的Adapter伞广。依賴IMulTypeHelper
接口,利用其getItemLayoutId()
方法去實現(xiàn)getView()
方法疼电,并暴露出onBindView()
供用戶快速使用嚼锄。
public abstract class MulTypeAdapter<T extends IMulTypeHelper> extends BaseAdapter<T> {
@Override
public View getView(ViewGroup parent, int pos, T data) {
View itemView = mInflater.inflate(data.getItemLayoutId(), parent, false);
onBindView(parent, itemView, data, pos);
return itemView;
}
/**
* 暴漏這個 讓外部bind數(shù)據(jù)
*
* @param parent
* @param itemView
* @param data
* @param pos
*/
public abstract void onBindView(ViewGroup parent, View itemView, T data, int pos);
}
IMulTypeHelper
接口,同樣簡單:
public interface IMulTypeHelper {
int getItemLayoutId();
}
總結
代碼傳送門:喜歡的話,隨手點個star蔽豺。多謝
https://github.com/mcxtzhang/all-base-adapter
因為想支持任意ViewGroup区丑,對ViewGroup代碼無侵入性,因而對部分功能進行了取舍修陡,例如設置OnItemXXXListener
,如果采用繼承ViewGroup沧侥,嵌入代碼,可以做到不強制addViews()
和setOnItemClickListener()
順序魄鸦。
通過上文我們能感受到一些面向接口編程的奧義宴杀,例如我們只需要設計好頂層的接口IViewGroupAdapter
,在沒寫剩下的xxxAdapter時拾因,工具類都可以寫好旺罢,編譯通過斯棒。
這在以后擴展時,例如主经,我數(shù)據(jù)集不能用List來保存了,我可能是多個List or Map 等等庭惜,只需要實現(xiàn)IViewGroupAdapter
接口即可定制一個Adapter罩驻。其他代碼不需任何修改。
有人說過护赊,設計模式怎么學惠遏,就是先學完一遍所有的設計模式。然后再全部忘掉他們骏啰,只要記住SOLID原則即可节吮。
我覺得很有道理,就像我之前一直在糾結代理模式和裝飾者模式的區(qū)別判耕,后來我想透绩,編碼時,我管它是什么模式壁熄,只要寫出來的是易維護的代碼即可帚豪。
to do list
- 考慮加入復用緩存池
- 考慮替換
onBindView()
的ItemView
->通用的ViewHolder
,這樣可以少寫一些findViewById()
代碼 - 整合DataBinding 的通用Adapter入庫草丧。
- 整合 RecyclerView狸臣、ListView的通用Adapter入庫。
- 加入一些自定義ViewGroup入庫昌执,例如流式布局烛亦,九宮格,Banner輪播圖懂拾。
下文預告:
一個用ScrollView很容易實現(xiàn)煤禽,但RecyclerView、ListView就無法實現(xiàn)的動畫效果委粉,仿淘寶會員中心等級動畫呜师。凸顯為所有ViewGroup增加Adapter模式的重要性。
DataBinding篇隆重登場
感興趣可以去閱讀
http://www.reibang.com/p/5ad655759c28
轉(zhuǎn)載請標明出處:
http://www.reibang.com/p/5ad655759c28
本文出自:【張旭童的簡書】 (http://www.reibang.com/users/8e91ff99b072/latest_articles)
代碼傳送門:喜歡的話贾节,隨手點個star汁汗。多謝
https://github.com/mcxtzhang/all-base-adapter