Android控制元件RecyclerView與ListView的異同
在我的一篇介紹Android新控制元件RecyclerView的部落格(Android L新控制元件RecyclerView簡介)中,一個讀者留言說RecyclerView跟ListView之間好像沒有什麼不同,我覺得這是一個好問題,應該明確地區分一下兩者的睯,所以我就研究了一下它倆之間的區別,然後也對兩者的使用有了更加深入的瞭解。
Android是一個不斷進化的平臺,Android 5.0的v7版本支援包中引入了新的RecyclerView控制元件,正如官方文件所言,RecyclerView是ListView的豪華增強版。它主要包含以下幾處新的特性,如ViewHolder,ItemDecorator,LayoutManager,SmothScroller以及增加或刪除item時item動畫等。官方推薦我們採用RecyclerView來取代ListView。
ViewHolder
ViewHolder是用來儲存檢視引用的類,無論是ListView亦或是RecyclerView。只不過在ListView中,ViewHolder需要自己來定義,且這只是一種推薦的使用方式,不使用當然也可以,這不是必須的。只不過不使用ViewHolder的話,ListView每次getView的時候都會呼叫findViewById(int),這將導致ListView效能展示遲緩。而在RecyclerView中使用RecyclerView.ViewHolder則變成了必須,儘管實現起來稍顯複雜,但它卻解決了ListView面臨的上述不使用自定義ViewHolder時所面臨的問題。RecyclerView.ViewHolder
LayoutManager
我們知道ListView只能在垂直方向上滾動,Android API沒有提供ListView在水平方向上面滾動的支援。或許有多種方式實現水平滑動,但是請想念我,ListView並不是設計來做這件事情的。但是RecyclerView相較於ListView,在滾動上面的功能擴充套件了許多。它可以支援多種型別列表的展示要求,主要如下:
GridLayoutManager,支援網格展示,可以水平或者豎直滾動,如展示圖片的畫廊。
ItemAnimator
列表動畫是一個全新的、擁有無限可能的維度。起初的Android API中,刪除或新增item時,item是無法產生動畫效果的。後面隨著Android的進化,Google的Chat Hasse推薦使用ViewPropertyAnimator屬性動畫來實現上述需求。
相比較於ListView,RecyclerView.ItemAnimator則被提供用於在RecyclerView新增、刪除或移動item時處理動畫效果。同時,如果你比較懶,不想自定義ItemAnimator,你還可以使用DefaultItemAnimator。
Adapter
ListView的Adapter中,getView是最重要的方法,它將檢視跟position繫結起來,是所有神奇的事情發生的地方。同時我們也能夠通過registerDataObserver在Adapter中註冊一個觀察者。RecyclerView也有這個特性,RecyclerView.AdapterDataObserver就是這個觀察者。ListView有三個Adapter的預設實現,分別是ArrayAdapter、CursorAdapter和SimpleCursorAdapter。然而,RecyclerView的Adapter則擁有除了內建的內DB遊標和ArrayList的支援之外的所有功能。RecyclerView.Adapter的實現的,我們必須採取措施將資料提供給Adapter,正如BaseAdapter對ListView所做的那樣。
ItemDecoration
在ListView中如果我們想要在item之間新增間隔符,我們只需要在佈局檔案中對ListView新增如下屬性即可:
1 android:divider="@android:color/transparent" 2 android:dividerHeight="5dp"View Code
有趣的是,RecyclerView在預設情況下並不在item之間展示間隔符。儘管Google的傢伙有意地將這個問題遺留給我們去自定義間隔符,但這的確增加了開發人員的負擔。如果你想要新增間隔符,你必須使用RecyclerView.ItemDecoration類來實現。或者,你可以應用官方示例中的DividerItemDecoration.java檔案。
OnItemTouchListener
ListView通過AdapterView.OnItemClickListener介面來探測點選事件。而RecyclerView則通過RecyclerView.OnItemTouchListener介面來探測觸控事件。它雖然增加了實現的難度,但是卻給予開發人員攔截觸控事件更多的控制權限。
Others
ListView可以設定選擇模式,並新增MultiChoiceModeListener,如下所示:
1 listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); 2 listView.setMultiChoiceModeListener(new MultiChoiceModeListener() { 3 public boolean onCreateActionMode(ActionMode mode, Menu menu) { ... } 4 public void onItemCheckedStateChanged(ActionMode mode, int position, 5 long id, boolean checked) { ... } 6 public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 7 switch (item.getItemId()) { 8 case R.id.menu_item_delete_crime: 9 CrimeAdapter adapter = (CrimeAdapter)getListAdapter(); 10 CrimeLab crimeLab = CrimeLab.get(getActivity()); 11 for (int i = adapter.getCount() - 1; i >= 0; i--) { 12 if (getListView().isItemChecked(i)) { 13 crimeLab.deleteCrime(adapter.getItem(i)); 14 } 15 } 16 mode.finish(); 17 adapter.notifyDataSetChanged(); 18 return true; 19 default: 20 return false; 21 } 22 public boolean onPrepareActionMode(ActionMode mode, Menu menu) { ... } 23 public void onDestroyActionMode(ActionMode mode) { ... } 24 });View Code
而RecyclerView則沒有此功能。
總之,通過比較我們可以發現,RecyclerView充滿了大量的自定義功能,它可以用於實現複雜的列表或網格,但實現起來稍顯得複雜。