RecyclerView與ListView比較

weixin_34320159發表於2018-03-26

RecyclerView 概述

RecyclerView 整合自 ViewGroup 。RecyclerView是Android-support-V7版本中新增的一個Widgets,官方對於它的介紹是:RecyclerView是ListView的升級版本,更加先進和靈活。

Android L 之後,Google 提供了RecyclerView檢視化控制元件,5.0之前如果想要使用的話,可以新增V7包以向下相容,提供更全面的API和更靈活的佈局管理。

RecyclerView 做了什麼

  • 類似ListView;
  • 類似GridView;
  • 橫向ListView;
  • 橫向GridView;
  • 瀑布流式佈局

RecyclerView 組成

  • RecyclerView.LayoutManager
  • RecyclerView.Recyler
  • RecyclerView.Adapter
  • RecyclerView.ViewHolder
  • RecyclerView.ItemDecoration
  • RecyclerView.ItemAnimator

機制:layoutmanager 從Recycle 中獲取已經繫結資料的 Item 顯示,並將不再需要的Item 丟給Recycler 回收;Adapter 負責生成新Item 並將其繫結好資料,供Recyle獲取;Recycler 就是子 Item 的一個快取池。

RecyclerView.LayoutManager -- 管理子View佈局的一個元件

主要負責:佈局子檢視、滾動子檢視在滾動過程中根據子檢視在佈局中所處的位置,決定何時新增子檢視和刪除子檢視。
涉及到的API:

  • 獲取佈局尺寸
    setRecyclerView()、setMeasureSpecs()、setMeasuredDimensionFromChildren()
  • 可以設定和獲取方向的水平或垂直
    canScrollHorizontally()、canScrollVertically()、setOrientation()、getOrientation()
  • 滑動狀態改變時RecyclerView呼叫方法通知LayoutManager
    onScrollStateChanged(()
  • 增、刪、移動子View
    addView()、removeView()、moveView()、removeAllViews()、removeViewAt()
  • 獲取指定位置的View
    getPosition()、getChildAt()、findViewByPosition()
  • 獲取可見子View及全部子View的個數
    getChildCount()、getItemCount()
  • 移除資料後呼叫了recycler進行資料的快取
    detachView()、detachAndScrapAttachedViews()、removeAndRecycleAllViews()、scrapOrRecycleView()

RecyclerView.Adapter 負責資料、Item的生成和資料的繫結

Adapter 有幾個抽象方法需要子類實現:

  • 返回一個ViewHolder 封裝例項
    onCreateViewHolder()
  • 根據ViewHolder對應的View進行資料繫結
    onBindViewHolder()
  • 獲取總數
    getItemCount()
  • 獲取不同Type型別的View,為新增 header 和 footer 預留介面
    getItemViewType()
  • 指定位置的 item 內容發生了變化
    notifyItemChanged()
  • 在指定的位置處插入一個 Item
    notifyItemInserted()
  • 指定位置的兩個 Item 進行交換
    notifyItemMoved(int, int)

RecyclerView.Recyler 負責 Item 的快取

即提供新的,也回收舊的(強大就強大在View的迴圈回收利用)

  • RecyclerView 的二級快取:
    有兩個快取:Scrap 和 Recycle ,Scrap 中文是廢料的意思。Recycle 對應是回收的意思。
    Scrap 快取是指裡面快取的View 是接下來需要用到的,不需要新繫結資料,是一個輕量級的快取集合,而Recycle 的快取的 View 為裡面的資料需要重新繫結,都放在RecyclerViewPool 池中,都需要通過 Adapter 重新繫結資料。
  • RecyclerView 快取的兩種方式:
    Detach 和 Remove ,Detach 的View 放在Scrap 快取中,Remove 掉的View 放在 RecyclerViewPool快取池中。
  • 使用場景:
    反覆去將View移除並且馬上又要新增進去時,選擇Detach 方式,通過方法 detachAndScrapView()實現。使用頻率很低,螢幕中不顯示的時候使用Remove 的方式,通過方法 removeAndRecycleView()實現。
  • 複用流程:
    當我們去獲取一個新的View時,首先去檢查Scrap 快取是否有對應的 position 的View ,如果有直接用;如果沒有,則從RecyclerViewPool快取池中取,並且會回撥Adapter 的onBindViewHolder 方法(如果Recycle 快取為空,還會呼叫onCreateViewHolder方法),最後再將繫結好新資料的View返回。

相關方法

與Recycler相關:

  • 獲取快取最大閥值,閥值為2
    setItemViewCacheSize()
  • 從快取中取Item
    getViewForPosition()
  • 獲取Scrap 快取列表
    getScrapList()
  • 從Layoutmanager 回收Item
    recyclerView()
  • 回收後,快取型別的內部處理邏輯
    recyclerViewHolderInternal()
  • 根據Adapter 變化,轉換Item 快取如pool
    onAdapterChanged()
  • 呼叫此方法返回一個RecyclerViewPool 例項
    getRecyclerView()
  • 快取如pool
    addViewHolderToRecyclerViewPool()

RecyclerViewPool 相關:

  • 快取的不同型別ViewType的數量是不限的,但是每個viewType 的具體ViewHolder 最多為5個
    setMaxRecycledViews(int viewType,int max)
  • 存入viewHolder
    putRecycledView()
  • 。。。
    getRecycledView()

RecyclerViw 與 listView 比較

  • Item 回收/複用方面:後者是以convertView 作為回收單位,需要手動新增ViewHolder ,而前者則是以ViewHolder作為回收單位,convertView 被內建到了ViewHolder 中作為 ViewHolder 的成員變數,前者內建了Recycle 、多級快取。
  • 樣式豐富方面:前者通過支援水平、垂直和變革列表及其他更復雜形式,而後者只支援具體某一種
  • 效果增強方面:前者內建了ItemDecoration 和 ItemAnimator ,可以自定義繪製 itemView 之間的一些特殊UI 或Item 項資料變化時的動畫效果,而yoga後者實現比較麻煩。
  • 程式碼內聚方面:前者將功能密切相關的類攜程內部類,如ViewHolder,Adapter。而後者沒有。

adapter用法

  • ListView 的 adapter
class MyAdapter extends BaseAdapter {    
    ……    
    @Override    
    public View getView(int position, View convertView, ViewGroup parent) {    
       ViewHolder holder = null;    
        if (convertView == null) {    
            holder = new ViewHolder();    
            …… //初始化convertView和ViewHolder    
            convertView.setTag(holder);    
        } else {    
            holder = (ViewHolder) convertView.getTag();    
        }    
       ……    
    }    
}    
static class ViewHolder {    
   TextView txvTitle;    
} 
  • RecyclerView 的 adapter
class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

       @Override
       public int getItemCount() {
           return 0;
       }

       @Override
       public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
           return null;
       }

       @Override
       public void onBindViewHolder(MyViewHolder holder, int position) {

       }

       class MyViewHolder extends RecyclerView.ViewHolder {
           //TODO 初始化控制元件   
           
           public MyViewHolder(View itemView) {
               super(itemView);
           }
       }
    }

最基礎的adapter,應用中列表會有許多,有多少個列表就會有幾個介面卡,可以根據需求封裝adapter,以方便使用。

相關文章