android v7相容包RecyclerView的使用(二),recyclerview

來源:互聯網
上載者:User

android v7相容包RecyclerView的使用(二),recyclerview

上篇文章 android v7相容包RecyclerView的使用(一)講了RecyclerView的最基本用法,現在開始挖掘更詳細的內容。
在RecyclerView的API中,有這樣一句話

A flexible view for providing a limited window into a large data set.

大致意思就是:當有大量的資料顯示在一個有限大小的視窗上時,RecyclerView就是解決這種情況的一個靈活的View。

從以上描述可以看出RecyclerView的使用情境。如果我們有大量的同一類型的資料要顯示在螢幕上,而此時很有可能整個螢幕無法完全顯示所有的資料,這時候RecyclerView就是一個合適的選擇。當使用者上下滾動螢幕的時候,item的迴圈重複利用也在同時進行,當一個新的item進入可視範圍,必然有一箇舊的item移出可視範圍,而這個被移出的item也就被迴圈重用。那麼迴圈重用item有什麼作用呢,其實他是很有用的一種方法,因為它節省了CPU資源和記憶體。

或許你會說我們用ListView用了很長的時間了,RecyclerView與我們以前的方式有什麼特別的地方呢,從前,我們使用listview的時候,顯示,迴圈重用以及其它的一些東西都有一定程度上的耦合性,現在RecyclerView則提供了一種更加靈活的方式。

Google現在使用的這種方法,它不在乎RecyclerView所看到的東西,也不在乎元素是否顯示在正確的地方,更不在乎每個元素是如何分隔的。RecyclerView做的事僅僅是是回收。因此得名RecyclerView。

下面是幾個和RecyclerView有關的最重要的類

Adapter:適配器,綁定資料集
ViewHolder:根據當前的資料儲存視圖
LayoutManager:布局管理器。決定item如何擺放
ItemDecoration:勉強理解為item裝飾器,可以美化item
ItemAnimator:動畫,當一個item被增加,刪除或者重新擺放時,會有動畫效果。

ViewHolder

安卓官方已經推薦使用ViewHolder模式有很長一段時間了,因為它能在一定程度上大大提高效率,介面流暢性增加。RecyclerView的適配器是一個內部類,我們通過繼承它來擴充我們的子類,就像這樣。

public final static class ListItemViewHolder extends RecyclerView.ViewHolder {   TextView title;//item介面上的一個元素   TextView description;//item介面上的一個元素   //當然可以繼續增加這些元素   public ListItemViewHolder(View itemView) {      super(itemView);      //關聯引用      title= (TextView) itemView.findViewById(R.id.title);      description= (TextView) itemView.findViewById(R.id.description);   }}
RecyclerView.Adapter

適配器完成兩個主要功能:負責建立基礎資料集和單個item布局之間的聯絡。適配器是Android的一個重要部分之一。它被用在許多地方,比如ListView, AutoCompleteTextView, Spinner都用到了適配器。

Google使用了RecyclerView的內部類Adapter代替了傳統的Adapter,所以在RecyclerView中,你不會見到類似SimpleCursorAdapter, ArrayAdapter這樣的適配器。

然而不幸的是Google並沒有提供RecyclerView.Adapter的預設實作類別,它是一個抽象類別,所以我們必須去實現三個方法。

public VH onCreateViewHolder(ViewGroup parent, int viewType)
public void onBindViewHolder(VH holder, int position)
public int getItemCount()

VH是一個繼承自ViewHolder的泛型,在子類中必須提供具體的類型。最基本的適配器寫法如下

public class RecyclerViewAdapter extends         RecyclerView.Adapter        <RecyclerViewAdapter.ItemViewHolder> {    private List<DemoModel> items;    RecyclerViewAdapter(List<DemoModel> modelData) {        if (modelData == null) {            throw new IllegalArgumentException(                  "modelData must not be null");        }        this.items = modelData;    }    @Override    public ItemViewHolder onCreateViewHolder(            ViewGroup viewGroup, int viewType) {        View itemView = LayoutInflater.                from(viewGroup.getContext()).                inflate(R.layout.item,viewGroup,false);        return new ItemViewHolder(itemView);    }    @Override    public void onBindViewHolder(            ItemViewHolder viewHolder, int position) {        DemoModel model = items.get(position);        viewHolder.title.setText(model.getTitle());        viewHolder.description.setText(model.getDescription());    }    @Override    public int getItemCount() {        return items.size();    }    public final static class ItemViewHolder            extends RecyclerView.ViewHolder {        // ... shown above in the ViewHolder section    }}
RecyclerView.LayoutManager

布局管理器是RecyclerView最有意思的一個地方,它負責對所有子item進行布局,在最新的v7相容庫中,它有三個實作類別,分別是LinearLayoutManager(線性布局),GridLayoutManager(a網格布局),StaggeredGridLayoutManager(流式布局),預設情況下,如果我們不設定布局管理器,將使用線性布局。我們可以通過繼承該類實現自己的布局管理器,由我們自己決定如何擺放item的內容,然而,當你去看上面的三個實作類別的代碼時,你會發現這是多麼不容易的一件事。。。代碼好長。。。真的!布局管理器的具體使用方法將再開一篇部落格,這裡先介紹一下線性布局管理器的簡單使用。代碼如下

//執行個體化對象LinearLayoutManager layoutManager = new LinearLayoutManager(context);//設定布局方向為豎直layoutManager.setOrientation(LinearLayoutManager.VERTICAL);//滾動到那一項layoutManager.scrollToPosition(currPos);//設定布局管理器recyclerView.setLayoutManager(layoutManager);
RecyclerView.ItemDecoration

姑且我叫它為item裝飾器,使用ItemDecoration我們可以給item增加位移量,增加item分割線,高亮等等。我們可以能增加很多個ItemDecoration,RecyclerView 會依次遍曆所有的ItemDecoration並調用繪圖方法去完成裝飾。它有三個抽象方法

public void onDraw(Canvas c, RecyclerView parent)
public void onDrawOver(Canvas c, RecyclerView parent)
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent)

在onDraw中繪製的內容可能會被item的內容遮擋,但是你在onDrawOver中繪製的內容會被繪製在item上方。我們可以使用位移量對item進行簡單分割,但是如果你想顯示一條分割線,你就不得不去使用onDrawOver方法去顯式的繪製一條分隔線。

布局管理器會在測量階段調用getItemOffset方法,它與一個Rect類型的參數,outRect 參數看上去有點怪怪的,那麼為什麼不用一個傳回值代替它呢,既然Google這樣做了,必然是有意義的。因為這樣可以讓所有item去複用一個Rect對象因此節約了資源,這樣做不一定是最好的,但是的確可以有效節約資源。

有一點要值得注意的是,onDraw()/onDrawOver()方法並不會為每個item調用,它只會被調用一次去繪製所有item的裝飾內容。因此我們必須在該方法中遍曆所有item進行繪製。

上篇文章簡單提供了一個DividerItemDecoration的源碼,當然我們可以通過繼承ItemDecoration 去實現更加豐富的內容。

RecyclerView.ItemAnimator

ItemAnimator類主要是處理動畫效果,以下三種情況,會觸發該動畫。

  • 一個item被添加到資料集中
  • 一個item從資料集中被移除
  • 一項在介面中位置被移動了

幸運的是,在v7相容包中提供了一個預設的實作類別叫做DefaultItemAnimator,如果我們不設定,預設就會適應該類。

如果想讓動畫生效,很明顯android必須知道資料改變了。在早期的適配器中,我們需要調用notifyDataSetChanged方法通知android資料集改變了。但是現在不再適用了,這個方法會重繪所有可見item但是不會觸發任何動畫,我們必須調用類似以下的方法才能觸發動畫。

public final void notifyItemInserted(int position)
public final void notifyItemRemoved(int position)

Listeners

監聽器,RecyclerView中不再有OnItemClickListener和OnItemLongClickListener監聽器,但是我們可以使用OnItemTouchListener再配合手勢去識別這些事件,這意味著我們需要編寫更多的代碼去實現同樣的效果。

綜上所述

在布局檔案中使用,代碼如下

     <android.support.v7.widget.RecyclerView        android:id="@+id/recyclerView"        android:layout_width="match_parent"        android:layout_height="match_parent"        tools:context=".MainActivity"        tools:listitem="@layout/item_demo_01"        />

tools屬性會渲染當前布局,當我們切換到可視化編輯器的時候可以看到效果,當然也可以不寫,只是看不到效果罷了。

我們可以看到,並沒有使用一些特別的屬性,實際上RecyclerView的屬性都是來自其父類ViewGroup。在RecyclerView中有一個方法用到了AttributeSet,這個方法就是generateLayoutParams,但是在內部它也並沒有怎麼對屬性進行操作。

@Overridepublic ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {   if (mLayout == null) {      throw new IllegalStateException("RecyclerView has no LayoutManager");   }   return mLayout.generateLayoutParams(getContext(), attrs);}

而在Activity中使用它也是很簡單的

//獲得控制項引用recyclerView = (RecyclerView) findViewById(R.id.recyclerView);//執行個體化布局管理器並設定布局管理器,滾動到頂部LinearLayoutManager layoutManager = new LinearLayoutManager(this);layoutManager.setOrientation(LinearLayoutManager.VERTICAL);layoutManager.scrollToPosition(0);recyclerView.setLayoutManager(layoutManager);// 當item大小一樣時有利於最佳化,具體怎麼個最佳化法我也不知道。。recyclerView.setHasFixedSize(true);// 綁定適配器並提供資料集List<DemoModel> items = new ArratList<DemoModel>();//......這裡進行資料的初始化工作adapter = new RecyclerViewDemoAdapter(items);recyclerView.setAdapter(adapter);//使用裝飾器,該類的源碼在上一篇文章中有提供RecyclerView.ItemDecoration itemDecoration =        new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST);//注意這裡是add而不是set,說明可以添加多個recyclerView.addItemDecoration(itemDecoration);// 下面這句話可以不寫,因為預設就是使用該類; // 當我們自訂了動畫,才有必要去設定recyclerView.setItemAnimator(new DefaultItemAnimator());// 設定監聽器,需要配合手勢//recyclerView.addOnItemTouchListener(this);

總結為以下幾步

基本源碼同上篇文章,源碼http://download.csdn.net/detail/sbsujjbcy/8489667

本篇文章參考了http://www.grokkingandroid.com/first-glance-androids-recyclerview/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.