1. 簡(jiǎn)介
RecyclerView是Android開發(fā)團(tuán)隊(duì)在Android5.0時(shí)推出旨在替換ListView的新UI控件(不過目前來(lái)看替換ListView還是不太可能滴)佣蓉。既然是被用來(lái)替換Listview的,自然RecyclerView不僅支持ListView原有的功能枫吧,而且它還有更多更優(yōu)秀的功能。
2. 基本概念
2.1 工作原理
RecyclerView的工作原理其實(shí)不難业岁,因?yàn)锳ndroid團(tuán)隊(duì)在它的命名上就為我們開發(fā)者們提示了它的工作原理掩宜。對(duì)!就是recycle(循環(huán)),當(dāng)我們?cè)诨瑒?dòng)視圖時(shí)并不是動(dòng)態(tài)的創(chuàng)建子項(xiàng)UI佳恬,因?yàn)槲覀兌贾肋@對(duì)于性能是很大的影響,所以RecyclerView是將子項(xiàng)UI放進(jìn)隊(duì)列或者循環(huán)箱中于游。這樣當(dāng)我們要滾入視圖時(shí)RecyclerView就會(huì)從中返回之前創(chuàng)建好的視圖給我們毁葱,同時(shí)滾出的視圖又會(huì)回到其中。整個(gè)過程就是不斷地再循環(huán)而已贰剥。
2.2 ViewHolder
ViewHolder又是什么東東呢头谜?我們?cè)谏厦婀ぷ髟頃r(shí)說(shuō)RecyclerView就是將子項(xiàng)UI放進(jìn)隊(duì)列或循環(huán)箱中。對(duì)鸠澈!ViewHolder就是用來(lái)存放子項(xiàng)UI的箱子柱告。不過這個(gè)箱子需要你自己來(lái)訂做喲截驮,這在下面基本用法時(shí)我會(huì)幫助你去創(chuàng)建它。
2.3 Adapter
既然RecyclerView是用來(lái)顯示數(shù)據(jù)的际度,可是我的數(shù)據(jù)源是怎么和RecyclerView連接的呢葵袭?騷年你能想到這里,說(shuō)明你根骨甚佳啊乖菱。對(duì)坡锡!Adapter就是它們約會(huì)的鵲橋啦。
2.4 Item Animation
不知道騷年你有沒有注意到窒所,其實(shí)當(dāng)你滑動(dòng)視圖時(shí)鹉勒,每一項(xiàng)視圖之間的轉(zhuǎn)換其實(shí)都是通過animator(動(dòng)畫)來(lái)實(shí)現(xiàn)的,這是它可能因?yàn)槠淠J(rèn)的設(shè)置方式就被你給忽略了吵取。
2.5 Layout Manager
可是騷年你想過沒有禽额?既然ViewHolder是決定怎么顯示單個(gè)視圖項(xiàng)的,那一堆的視圖項(xiàng)就是許多的ViewHolder組合在一起嗎皮官?當(dāng)然不是脯倒!因?yàn)槟菢幼鐾耆珱]有意義,你只會(huì)寫很多重復(fù)代碼以至于把你累垮= =捺氢。這時(shí)LayoutManager就應(yīng)運(yùn)而生了藻丢。而且它還決定著何時(shí)回收對(duì)用戶不可見的子項(xiàng)視圖,所以它的確是個(gè)好管家摄乒。
3. 基本用法
3.1 添加依賴
在項(xiàng)目目錄下的build.gradle文件中添加這行代碼悠反。
dependencies {
compile 'com.android.support:recyclerview-v7:25.1.0'
}
需要注意的是這里我的RecyclerView版本號(hào)是25.1.0,你的沒必要跟我相同馍佑。
3.2 創(chuàng)建RecyclerView與Item布局
RecyclerView布局
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Item布局
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
這里我為了舉例斋否,所以這個(gè)item布局只是一個(gè)FrameLayout布局加一個(gè)TextView,非常簡(jiǎn)單挤茄。
3.3 創(chuàng)建ViewHolder
現(xiàn)在我們來(lái)學(xué)一學(xué)如何自己訂做“箱子”如叼。Android提供了“箱子”的模板也就是給我們提供了一個(gè)抽象類冰木。我們根據(jù)這個(gè)模板穷劈,也就是繼承RecyclerView.ViewHolder這個(gè)類。
public class CustomViewHolder extends RecyclerView.ViewHolder{
public final TextView item;
public CustomViewHolder(View v) {
super(v);
item = (TextView) v.findViewById(R.id.tv_item);
}
}
這里你可能會(huì)問就這么簡(jiǎn)單嗎踊沸?是的歇终,騷年我這里只能這么簡(jiǎn)單,更多的東西需要根據(jù)你自己的需求來(lái)添加逼龟。
3.4 創(chuàng)建Adapter
上面介紹時(shí)我們說(shuō)了评凝,Adapter是RecyclerView和數(shù)據(jù)之間約會(huì)的鵲橋,那么應(yīng)該怎么來(lái)完成這個(gè)約會(huì)的重要組成部分的搭建呢腺律?首先我們需要知道Android并沒有提供Adapter的實(shí)現(xiàn)類奕短,而是提供了一個(gè)叫做RecyclerView.Adapter<ViewHolder>的Adapter類來(lái)讓我們繼承宜肉。我們都知道鵲橋是由喜鵲搭建的,那么Adapter中的喜鵲是什么呢翎碑?以下這三個(gè)需要在繼承Adapter類時(shí)重寫的方法就是搭建Adapter的喜鵲了谬返。
-
ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
這
只喜鵲個(gè)方法會(huì)在RecyclerView實(shí)例化一個(gè)新的ViewHolder時(shí)被調(diào)用。 -
void onBindViewHolder(ViewHolder holder, int position)
這個(gè)方法會(huì)在RecyclerView想我們的數(shù)據(jù)源填充視圖并且呈現(xiàn)給用戶時(shí)調(diào)用日杈。
-
int getItemCount()
這個(gè)方法它僅僅是簡(jiǎn)單的返回?cái)?shù)據(jù)源中的項(xiàng)目數(shù)遣铝。
下面是一個(gè)簡(jiǎn)單的Adapter類的寫法。
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> { private int mItems; public NormalAdapter(int items) { mItems = items; } @Override public VH onCreateViewHolder(ViewGroup parent, int viewType) { Context context = parent.getContext(); int layoutIdForListItem = R.layout.list_item; LayoutInflater inflater = LayoutInflater.from(context); boolean shouldAttachToParentImmediately = false; View view = inflater.inflate(layoutIdForListItem, parent, shouldAttachToParentImmediately); CustomViewHolder viewHolder = new CustomViewHolder(view); return viewHolder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.bind(position); } @Override public int getItemCount() { return mItems; } public class CustomViewHolder extends RecyclerView.ViewHolder{ public final TextView item; public CustomViewHolder(View v) { super(v); item = (TextView) v.findViewById(R.id.tv_item); } void bind(int listIndex) { item.setText(String.valueOf(listIndex)); } } }
不知道你發(fā)現(xiàn)沒莉擒,其實(shí)我們之前寫的ViewHolder類其實(shí)是Adapter的一個(gè)內(nèi)部類酿炸。此外這里我這個(gè)Adapter類寫的并不怎么好,推薦你看看我下面參考資料中的騰訊Bugly公眾號(hào)的RecyclerView 必知必會(huì)涨冀,他里面有說(shuō)到萬(wàn)能Adapter的寫法填硕。
3.5 連接RecyclerView
通過我們上面一步步地搭建,現(xiàn)在這個(gè)鵲橋算是基本完成了蝇裤。我們現(xiàn)在就通過LayoutManager來(lái)讓RecyclerView和我們的數(shù)據(jù)源“甜蜜的約會(huì)”吧廷支。不過在貼代碼之前,我還想再跟你說(shuō)點(diǎn)關(guān)于LayoutManager的事兒栓辜。
LayoutManager由以下三種實(shí)現(xiàn):
- LinearLayoutManager 線性布局
- GridLayoutManager 網(wǎng)格布局
- StaggeredGridLayoutManager 錯(cuò)列網(wǎng)格布局(也稱之為瀑布流布局)
因?yàn)槲抑皇呛?jiǎn)單的介紹恋拍,所以我以使用最為廣泛LinearLayoutManager為例來(lái)實(shí)現(xiàn)連接過程。
mRecyclerview = (RecyclerView) findViewById(R.id.rv_list);
/*
* 線性布局既然稱之為線性藕甩,自然它肯定有橫向與縱向兩個(gè)方向施敢,而默認(rèn)的方式是縱向的。
*/
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerview.setLayoutManager(layoutManager);
/*
* 這個(gè)方法可以對(duì)UI進(jìn)行一些優(yōu)化狭莱,它能使UI在適配器內(nèi)容改變時(shí)避免使整個(gè)布局無(wú)效
*/
mNumbersList.setHasFixedSize(true);
這里我就只是簡(jiǎn)單的給你介紹下僵娃,想要了解更多的關(guān)于LayoutManager的知識(shí),你可以在我下面的推薦資料中找到腋妙。
3.6 處理點(diǎn)擊事件
當(dāng)你把RecyclerView和數(shù)據(jù)連接之后默怨,你卻發(fā)現(xiàn)為啥不能點(diǎn)啊喂?騷年骤素,你還忘了點(diǎn)擊事件處理啊匙睹。你可能又會(huì)問那為啥RecyclerView不提供點(diǎn)擊事件處理,要我自己來(lái)處理济竹?因?yàn)锳ndroid開發(fā)團(tuán)隊(duì)并不知道你會(huì)點(diǎn)擊的是單項(xiàng)中的圖片or文字痕檬,所以他們就把這項(xiàng)任務(wù)交給你自己來(lái)做。這也是RecyclerView比ListView優(yōu)秀的地方送浊。
下面是我根據(jù)當(dāng)初在Android開發(fā)者官網(wǎng)的Training中學(xué)到的方法梦谜。在Adapter中自己定義一個(gè)點(diǎn)擊監(jiān)聽器接口,然后在ViewHolder中實(shí)現(xiàn)view.OnClickListener接口,在onClick()中再調(diào)用我們自己定義的接口唁桩。最后在RecyclerView所在的Activity中實(shí)現(xiàn)接口中自定義的方法闭树。或許這看起來(lái)會(huì)有點(diǎn)復(fù)雜荒澡,不過這個(gè)方法優(yōu)秀在你可以把點(diǎn)擊事件的處理和Adapter分開蔼啦,以至于更好的擴(kuò)展。
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> {
final private ItemClickListener mOnClickListener;
public interface ListItemClickListener {
void onListItemClick(int clickedItemIndex);
}
public class CustomViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
public final TextView item;
public CustomViewHolder(View v) {
super(v);
item = (TextView) v.findViewById(R.id.tv_item);
}
@Override
public void onClick(View v) {
mOnClickListener.onItemClick();
}
}
如果你一下理解不了這里的內(nèi)容仰猖,是沒有關(guān)系的捏肢。
4. 參考資料
如果在你看完我這篇關(guān)于RecyclerView的簡(jiǎn)單介紹之后,你還不夠滿足的話饥侵。我的承認(rèn)騷年你也是一個(gè)跟我一樣愛學(xué)習(xí)的三好青年辣(豎起了我的大拇指)鸵赫!所以我也為你準(zhǔn)備了一些參考資料,接下來(lái)的學(xué)習(xí)就由它們來(lái)幫助你吧躏升!
android開發(fā)游記:RecyclerView無(wú)法添加onItemClickListener最佳的高效解決方案
騰訊Bugly公眾號(hào)(weixinBugly):RecyclerView 必知必會(huì)
Android開發(fā)者官網(wǎng):RecyclerView
5. 寫在最后的話
更多Android開發(fā)文章請(qǐng)點(diǎn)擊我的主頁(yè)查看辩棒,謝謝你閱讀我的文章。