Android RecyclerView體驗(一)- 簡介

在網上關於RecyclerView的基本使用方式已經有了比較詳細介紹,並且其設計結構也相似於ListView,因此本文將不重點介紹如何使用,在文末的引用中均可以相關內容。這裏主要是介紹RecyclerView的基本功能、設計理念,以及系統提供API的狀況。android

 

什麼是RecycleView

RecyclerView是在Android L(也就是後來的Lollipop)中新加入的一種ViewGroup。但由於它使以support-v7庫的形式加入到Android系統中,因此不只僅是Lollipop版本之後的Android系統可使用,只要系開發項目中引入這個庫就在任意API級別中使用。git

單從呈現效果來看RecyclerView和ListView、GridView並無大多的差異。github

不過它的「flexible」並不僅僅指它能夠在ListView和GridView之間隨意互相切換,更在於它能夠創造出更多的複雜的可滾動的視圖,好比水平方向的ListView,或者是Web上很流行的瀑布流式佈局(Masonry)。只是大部分佈局系統都沒有提供,必須由開發者本身實現。佈局

因此RecyclerView的「flexible」:什麼均可以作,但什麼都要本身作。flex

 

RecyclerView和ListView的主要區別

只要用Android提供的LieanerLayoutManager並配以VERTICAL模式,RecyclerView就能夠完美達到ListView的基本效果。二者的設計結構也都是數據(Dataset)與視圖(View)分離,而後經過適配器(Adapter)來鏈接的方式。動畫

但RecyclerView相對ListView來講有如下幾大提高:spa

  • 沒有OnItemClickListener

ListView從它的父類AdapterView直接繼承了對子項目點擊的響應,開發者能夠定義本身的OnItemClickListner來接受點擊事件。但這個設計也形成了一些問題,好比子項內部視圖若是設置了OnClickListener,那麼子項目視圖自己並不會知道,從而可能會致使視圖點擊狀態沒有同步等問題。ReyclerView沒有提供簡便的響應子項目被點擊的監聽器,雖然它有一個OnItemTouchListener,但在這個接口方法中沒有任何關於那個子項目被點擊的信息,該接口只是幫助開發者截獲觸摸事件,對於如何處理,檢測被觸摸目標對象都留給了開發者去完成。設計

  • 視圖與佈局分離

ListView作到了數據和視圖的分離,RecyclerView在視圖和佈局之間再進一步分離,因而便有了LayoutManager。RecyclerView負責管理視圖的重複利用,而後將佈局方式全權交給了LayoutManager,經過配置或者切換LayoutManager就能夠得到不一樣的佈局效果。不像ListView被限制在垂直滾動佈局。同時RecyclerView還提供了ItemDecoration,在已有的子視圖基礎上還能夠添加額外的視圖。好比作一條分割線,在ListView就須要額外佔用一個ViewType來提供視圖,如今則不須要在Adapter中加入這些與實際邏輯業務無關的輔助內容code

  • 支持子項目層次的動畫效果

ListView也能夠支持子項目層次的動畫效果,在Android Developers的DevBytes頻道里有不少關於這方面的介紹,不過在看過其實現以後就會發現其解決方案是多麼的醜陋而冗長。不少時候都是在計算和分析子視圖的位置狀態。RecyclerView則帶來了很是簡潔的ItemAnimator接口。當Adapter中的數據發生「增刪改移」變化,經過調用Adapter相應的方法就能夠激活動畫的產生。固然開發者還須要本身實現具體的ItemAnimator對象來完成所需的動畫效果,可是其清晰的結構和接口已比ListView有極大的進步。對象

 

RecyclerView的現狀

上邊提到RecyclerView的套件已經加入了Support Library v7,並且是以單獨的庫放入,因此只要在Android Studio項目的Gradle編譯文件的dependencies下加入下邊的這句就能夠開始使用RecyclerView了:

compile 'com.android.support:recyclerview-v7:25.x.x'
不過看過庫中提供的那些自帶對象實現,體現基本操做流程,就會發現RecyclerView能作的看起來不少,可是已經作到的實在太少。

RecyclerView.Adaper

RecyclerView提供了一個抽象Adapter類,而後就沒有了。沒有任何能夠直接使用的子類,像ListAdapter那樣的ArrayAdapter、SimpleCursorAdapter現成的類都沒有。一切都留給開發者本身去實現定義。

仔細想一想這也很挺正常,相信應該不多在實際產品中有使用ArrayAdapter的,由於大部分列表都不會是簡單的一行文字。對於CursorAdapter使用也每每會實現不一樣的繼承類來提供子視圖。再者RecyclerView的Adapter和ListAdapter在理念上仍是同樣的,因此想實現個RecyclerViewCursorAdapter,直接從CursorAdapter取材即可。

RecyclerView的Adapter相對ListAdapter在接口上有幾處變化也值得注意。

  首先其將getView()方法分拆成了createViewHolder()bindViewHolder()兩個。不過這個沒有什麼好緊張的,在CursorAdapter裏就已經有見到過這個更加合理的設計。另外返回對象也從View變成了ViewHolder只需提一下。

最關鍵的注意點在於createViewHolder(ViewGroup parent, int viewType)第二參數雖然是整形,可是它並非以往的當前子項的位置(position),而是調用getItemViewType()得到的的子項的類別。彷佛在建立ViewHolder時,RecyclerView故意在隱藏子項的詳細信息,但願開發者徹底只依賴其類別來建立相應的View以及ViewHolder。

其次,RecyclerView的Adapter除了和ListAdapter同樣有notifyDataSetChanged()方法外,還有一堆會觸發動畫效果的通知數據改變的方法:

  • final void notifyItemChanged(int position); // 修改
  • final void notifyItemInserted(int position); // 插入
  • final void notifyItemMoved(int fromPosition, int toPosition); // 移動
  • final void notifyItemRangeChanged(int positionStart, int itemCount); // 批量改變
  • final void notifyItemRangeInserted(int positionStart, int itemCount); // 批量插入
  • final void notifyItemRangeRemoved(int positionStart, int itemCount); // 批量刪除
  • final void notifyItemRemoved(int position); // 刪除某個

調用這些方法就會激發ItemAnimator上對應的用於產生動畫的方法。

 

RecyclerView.ViewHolder

在ListView的年代裏,其實已經在使用ViewHolder,只是那時的方法看起來比較討巧,要隱藏在View的Tag()裏。如今RecyclerView強制使用ViewHolder,而且ViewHolder除了有對子視圖的引用,還有諸如ItemViewType和Position這些信息。

mHolder.getItemViewType(); // 獲取當前Holder類型
mHolder.getAdapterPosition(); // 獲取當前的position(當有刪除/新增item時,會時時更新),所以可替代經過Tag獲取數據。

 

RecyclerView.LayoutManager

LayoutManager相對於ListView來講是一個新部分,經過繼承該類來實現自定義的佈局方式,而不像ListView只有固定的佈局方式。Support庫提供了兩個現成的子類:LinearLayoutManagerStaggeredGridLayoutManager。前者能夠得到和ListView同樣的佈局,還能夠是水平方向的;後者則提供了形如GridView的佈局。因此應用程序中的基本平常因此均可以被知足。

若是須要實現自定義的LayoutManager,就比較麻煩了,須要理解Recycle、Scrap、Dirty這些關於子項目視圖狀態的概念。

 

RecyclerView.ItemAnimator

經過繼承實現ItemAnimator,而後建立對象設置到RecyclerView上就能夠獲得基於子項目的動畫效果。不過如何正確合理地建立一個ItemAnimator子類,卻沒有詳細的描述指南。

庫中提供的惟一一個可用的子類DefaultItemAnimator,能夠看出它的動畫效果是簡單的Alpha漸變。同時也會發現其實現是如此的複雜,有不少對於動畫步驟的操做,還得注意動畫在中途被打斷的處理,在結束時也要重置視圖狀態以便重用。這也反過來講明ItemAnimator基本沒有提供任何關於如何實現和管理動畫的信息。另外一方面由於DefaultItemAnimator的實現過於具體,所以它並非合適做爲自定義ItemAnimator的父類。

相信當RecyclerView愈來愈多的被應用到程序中時,更多關於這方面的合理設計會被提出來。目前在Github上也有很多參考了DefaultItemAnimator的實現方式,好比RecyclerViewItemAnimatorsrecyclerview-animators

關於ItemAnimator的使用,有幾點值得提醒的是:若是沒有提供ItemAnimator,RecyclerView默認會建立一個DefaultItemAnimator用於動畫,因此不須要顯示地設置DefaultItemAnimator對象到RecyclerView上;添加(add)和刪除(remove)是默認起效的,可是修改(change)的效果須要調用setSupportsChangeAnimations(boolean)來指定是否啓用,其默認是沒有修改的動畫。

 

 

整體而言,RecyclerView的功能很是強大,其結構設計也十分開放,這也形成它的上手使用相對比較困難。隨着愈來愈多的人開始嘗試使用這個部件,也會有愈來愈深入的理解和設計實現。另外,閱讀RecyclerView的源碼能夠幫助對其設計思想的瞭解,在之後設計其它的複用視圖時能夠有更好的參照。

相關文章
相關標籤/搜索