1 Introduction
android.support.v7.recyclerview
在Android 5.0之后蕉斜,Google推出RecyclerView來取代ListView。官方是這樣介紹的:
A flexible view for providing a limited window into a large data set.
和ListView一樣茂翔,RecyclerView用于顯示列表形式的界面,并且通過復(fù)用View的方式來節(jié)約系統(tǒng)資源费就,甚至和ListView一樣通過Adapter來渲染數(shù)據(jù)过蹂。那么我們為什么要使用RecyclerView呢?自然要說下歪赢,二者的區(qū)別:
- RecyclerView自動地幫我們實現(xiàn)了itemView的重復(fù)利用,而強(qiáng)制開發(fā)者去繼承
RecyclerView.ViewHolder
來實現(xiàn)一個ViewHolder來管理與itemView相關(guān)的位置信息及其他數(shù)據(jù)单料。 - RecyclerView必須設(shè)置各種
LayoutManager
來實現(xiàn)GridView埋凯、ListView甚至瀑布流的效果。 - ListView擁有
android:divider
屬性輕松實現(xiàn)條目之間的統(tǒng)一分隔線扫尖,而RecyclerView需要一個RecyclerView.ItemDecoration
對象來設(shè)置各種各樣的分隔線白对。可以達(dá)到不同條目不同分隔線的效果换怖,而不是像ListView那樣只能通過將分隔線寫進(jìn)itemView布局的方式來實現(xiàn)甩恼。 - ListView沒有提供方法來控制添加/刪除條目時的動畫,而RecyclerView有
RecyclerView.ItemAnimator
來控制條目動畫沉颂。 - ListView擁有
AdapterView.OnItemClickListener
來處理每個條目的點擊事件条摸。而RecyclerView只有RecyclerView.OnItemTouchListener
來處理MotionEvent,而并沒有一個內(nèi)置的點擊事件處理铸屉。 - 當(dāng)列表數(shù)據(jù)發(fā)生改變時钉蒲,ListView只有一個
notifyDataSetChanged()
方法來刷新所有條目。而RecyclerView提供了notifyItemChanged()
彻坛、notifyItemInserted()
顷啼、notifyItemRemoved()
、notifyDataSetChanged()
等方法昌屉,內(nèi)部實現(xiàn)了局部刷新钙蒙,更加高效。
所以由上面幾點可以看出间驮,RecyclerView可以實現(xiàn)和ListView一樣的界面躬厌,但是比ListView要靈活得多,同時其內(nèi)部自動實現(xiàn)了itemView的重用蜻牢。靈活的代價意味著開發(fā)者在配置控件時需要做更多工作烤咧,RecyclerView的分隔線偏陪、點擊事件分發(fā)抢呆、條目動畫都要自己去實現(xiàn),所以本文就推薦一些好用的RecyclerView輪子笛谦。
2 萬能分隔線RecyclerView-FlexibleDivider
yqritc/RecyclerView-FlexibleDivider
框架提供了HorizontalDividerItemDecoration
和VerticalDividerItemDecoration
分別對應(yīng)水平/豎直的divider抱虐。
通過Builder的方式構(gòu)造分隔線,你可以很方便地設(shè)置分隔線的margin饥脑、顏色恳邀、粗細(xì)甚至圖案:
recyclerView.addItemDecoration(
new HorizontalDividerItemDecoration.Builder(this)
.color(Color.RED)
.sizeResId(R.dimen.divider)
.marginResId(R.dimen.leftmargin, R.dimen.rightmargin)
.build());
也可以通過實現(xiàn)各種Provider
接口懦冰,來設(shè)置不同位置不同樣式的分隔線:
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this)
.sizeProvider(new FlexibleDividerDecoration.SizeProvider(){
@Override
public int dividerSize(int position, RecyclerView parent) {
switch (position % 10) {//不同位置不同高度
case 0:
return 30;
case 1:
return 10;
default:
return 2+position;
}
}
})
.build());
3 各式各樣的ItemAnimator實現(xiàn)
gabrielemariotti/RecyclerViewItemAnimators
提供包括SlideInOutLeftItemAnimator 、SlideInOutRightItemAnimator 谣沸、SlideInOutTopItemAnimator 刷钢、SlideInOutBottomItemAnimator 、ScaleInOutItemAnimator 在內(nèi)的各種自定義條目動畫效果的實現(xiàn)乳附。
- 單個條目的動畫設(shè)置:
mRecyclerView.setItemAnimator(new SlideInOutLeftItemAnimator(mRecyclerView));
- 整個列表的動畫設(shè)置:
mAdapter = new MyAdapter(this);
//通過AlphaAnimatorAdapter來包裝 原來的列表adapter
AlphaAnimatorAdapter animatorAdapter = new AlphaAnimatorAdapter(mAdapter, mRecyclerView);
mRecyclerView.setAdapter(animatorAdapter);
4 支持復(fù)雜的多類型列表視圖
drakeet/MultiType
項目中經(jīng)常會需要寫一個復(fù)雜的内地、多 itemView types 的列表視圖,經(jīng)常要做一堆繁瑣的工作赋除,而且不小心的話代碼還堆積嚴(yán)重:我們需要覆寫RecyclerView.Adapter的 getItemViewType()
方法阱缓,并新增一些 type 整形常量,而且 ViewHolder繼承举农、泛型傳遞荆针、轉(zhuǎn)型也比較糟糕。
通過這個庫可以輕松簡單地實現(xiàn)包含多種不同類型條目的列表:
- 列表中的數(shù)據(jù)必須實現(xiàn)
Item
接口 - 創(chuàng)建一個類繼承
ItemViewProvider
颁糟,里面指定了某個Item Type的布局和這個條目對應(yīng)的RecyclerView.ViewHolder
航背。 - 在Application 中進(jìn)行注冊類型:
public class App extends Application {
@Override public void onCreate() {
super.onCreate();
MultiTypePool.register(TextItem.class, new TextItemViewProvider());
MultiTypePool.register(ImageItem.class, new ImageItemViewProvider());
}
}
- 然后創(chuàng)建
MultiTypeAdapter
,將數(shù)據(jù)集合(實現(xiàn)Item
接口的javaBean的集合)設(shè)置進(jìn)去即可棱貌。
recyclerView.setAdapter(new MultiTypeAdapter(items));
十分簡單優(yōu)雅有木有沃粗?!
類似的還有sockeqwe/AdapterDelegates
5 點擊事件的分發(fā)
RecyclerView并沒有提供一個OnItemClickListener
給開發(fā)者去處理條目的點擊事件键畴。最簡單的辦法是自己寫個回調(diào)接口最盅,然后給itemView設(shè)置onClick時去觸發(fā)這個回調(diào)接口。
RecyclerView無法添加onItemClickListener最佳的高效解決方案這篇文章通過 recyclerView.addOnItemTouchListener()
和系統(tǒng)提供的 GestureDetector
手勢判斷結(jié)合實現(xiàn)的起惕∥屑總感覺把簡單的問題復(fù)雜化了。
這里有一個簡單的工具類可以方便實現(xiàn): ItemClickSupport decorator惹想,使用起來十分簡單:
ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(
new ItemClickSupport.OnItemClickListener() {
@Override
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
// do something.
}
});
6 對Adapter的一些封裝
避免自定義Adapter時造成過多的重復(fù)代碼问词。且通過裝飾者模式優(yōu)雅地為RecyclerView添加header或者footer:
hongyangAndroid/baseAdapter
主要是在項目中使用RecyclerView.Adapter可以參考這個開源框架的一些思路,做一些優(yōu)雅的封裝嘀粱。