天天看點

RecycleView的基本使用方法

為什麼要使用RecycleView,而不再使用ListView

記得每一次在用ListView的時候,在Adapter中,總是需要我們自己去建立一個ViewHolder,去存儲ListItem的布局,這麼做的原因在于findViewById()是一個很耗時間的操作,是以我們需要一個靜态的對象将layout過的控件給儲存起來,下一次重新整理這個item的時候,就不再需要調用findViewById去ViewTree中初始化控制,進而達到對ListView的優化效果。

而RecycleView則已經幫我們封閉好了這樣一個ViewHolder的抽象類RecycleView.ViewHolder,而且是必須實作的一個接口,這說明在控制節省記憶體方面,RecycleView要比ListView做得要好,因為在ListView中,你不寫ViewHolder也是可以的。

此外,ListView的設計是一個上下滑動的清單控制,而RecycleView則通過一個LayoutManager來實作多種布局的展現,包括縱向清單,橫向Gallery,Grid布局,基于瀑布流等,可以說,之前通過ListView, GridView, ViewPager等實作的布局,現在用一個RecycleView就可以實作了。

再此外,現在的很多app,就算是使用ListView,也不僅僅是單純地展現資料,都希望能夠利用一些平滑的動畫效果來提升使用者體驗,而RecycleView本身在對資料的增删上就添加了對動畫的效果的的支援。

在RecyclerView中增加了以下的接口:

public final void notifyItemInserted(int position) {
            mObservable.notifyItemRangeInserted(position, );
        }
        public final void notifyItemMoved(int fromPosition, int toPosition) {
            mObservable.notifyItemMoved(fromPosition, toPosition);
        }  

    public void setItemAnimator(ItemAnimator animator) {
        if (mItemAnimator != null) {
            mItemAnimator.endAnimations();
            mItemAnimator.setListener(null);
        }
        mItemAnimator = animator;
        if (mItemAnimator != null) {
            mItemAnimator.setListener(mItemAnimatorListener);
        }
    }       
           

綜合種種,個人覺得,是很有必要掌握一下如何使用RecycleView的。

如何使用 RecycleView

RecycleView是Support-v7包中的元件,是以在Gradle中,我們要添加其對應的引用

dependencies {
    ...
    compile 'com.android.support:recyclerview-v7:23.1.0'
    ...
}
           

在xml布局中,如下使用

<android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe_refresh_widget"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/order_list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="@dimen/normal_space" />
    </android.support.v4.widget.SwipeRefreshLayout>
           

在Activity中,

private RecyclerView mOrderListView;
    private LinearLayoutManager mLayoutManager;
    private OrderListRecycleViewAdapter mOrderListAdapter;

    mOrderListView = (RecyclerView) findViewById(R.id.order_list);
    mLayoutManager = new LinearLayoutManager(this);
    mOrderListView.setHasFixedSize(true);
    mOrderListView.setLayoutManager(mLayoutManager);
    mOrderListAdapter = new OrderListRecycleViewAdapter(this, mOrderList, this);
    mOrderListView.setAdapter(mOrderListAdapter);
           

這裡可看到分為幾步:

  • 聲明LayoutManager,并調用RecycleView的setLayoutManager方法進行指派

目前SDK中提供了三種LayoutManager,分别為

  • LinearLayoutManager
  • GridLayoutManager
  • StaggeredGridLayoutManager

使用不同的LayoutManager,分别如下:

  • 使用LinearLayoutManager
mLayoutManager = new LinearLayoutManager(this)
           
  • 使用GridLayoutManager
mLayoutManager = new GridLayoutManager(this, , LinearLayoutManager.Vertical, false)
           

GridLayoutManager的構造有如下幾種:

/**
     * Creates a vertical GridLayoutManager
     *
     * @param context Current context, will be used to access resources.
     * @param spanCount The number of columns in the grid
     */
    public GridLayoutManager(Context context, int spanCount) {
        super(context);
        setSpanCount(spanCount);
    }

    /**
     * @param context Current context, will be used to access resources.
     * @param spanCount The number of columns or rows in the grid
     * @param orientation Layout orientation. Should be {@link #HORIZONTAL} or {@link
     *                      #VERTICAL}.
     * @param reverseLayout When set to true, layouts from end to start.
     */
    public GridLayoutManager(Context context, int spanCount, int orientation,
            boolean reverseLayout) {
        super(context, orientation, reverseLayout);
        setSpanCount(spanCount);
    }
           

在這裡,按照我們上述的聲明,其實作的效果跟LinearLayout的效果是一緻的,當SpanCount值大于1的時候,就能夠以格式的效果展現,這種切換其實還是挺簡單的,是不?

  • StaggeredGridLayoutManager
StaggeredGridLayoutManager mLayoutManager = new StaggeredGridLayoutManager(, StaggeredGridLayoutManager.VERTICAL);
           

看效果就已經能夠實作簡單的瀑布流了。

接下來還要對recycleView設定以下的方法:

  1. 設定hasFixedSize方法

    調用此方法,可讓RecycleView保持展現的item數目,在RecycleView的實作中會有一些優化。

  2. 聲明Adapter,将調用RecycleView的setAdapter方法進行指派。

到這裡,除了去實作 Adapter之後,對RecycleView的初始化及使用,到此即可。

除此之外,我們還能夠調用RecycleView的addItemDecoration方法和setItemAnimator方法來自定義item的分隔線及item的動畫效果。

mOrderListView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));

mOrderListView.setItemAnimator(new DefaultItemAnimator());
           

實作Adapter

我們實作的Adapter必須繼承于RecycleView.Adapter,如下

而需要我們去實作的方法,如下展示:

@Override
public int getItemViewType(int position) {
    if (position +  == getItemCount()) {
        return TYPE_FOOTER;
    } else {
        return TYPE_ITEM;
    }
}

@Override
 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
     if (TYPE_ITEM == viewType) {
         View view = LayoutInflater.from(mContext).inflate(R.layout.order_list_item, parent, false);
         return new OrderListViewHolder(view);
     } else {
         View view = LayoutInflater.from(mContext).inflate(R.layout.list_footer, parent, false);
         return new OrderListFooterHolder(view);
     }
 }

   @Override
  public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
      if (holder instanceof OrderListViewHolder) {
          Order order = mData.get(position);
          OrderListViewHolder itemHolder = (OrderListViewHolder) holder;
          ...
      } else if (holder instanceof OrderListFooterHolder) {
          OrderListFooterHolder footerHolder = (OrderListFooterHolder) holder;
         ...
      }
  }

@Override
public int getItemCount() {
    return mData.size() + ;
}

static class OrderListFooterHolder extends RecyclerView.ViewHolder {
    TextView itemFooter;

    public OrderListFooterHolder(View itemView) {
        super(itemView);
        itemFooter = (TextView) itemView.findViewById(R.id.item_footer);
    }
}

static class OrderListViewHolder extends RecyclerView.ViewHolder {
      ....
      public OrderListViewHolder(View itemView) {
          super(itemView);
          ...
      }
  }
           

在上面這個Adapter中,其實做了幾件事:

  1. public int getItemViewType(int position)

    根據getItemViewType傳回我們要去加載的item布局,這一個方法的實作不是必須的,在這裡隻是因為需要去加載兩個布局,是以就定義了兩個ITEM_TYPE,如果就一個布局,這方法可以不實作。

  2. public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)

    如果有不同的viewType,我們則必須根據不同的viewType來從不同的item布局中,利用LayoutInflater來加載,并建立對應的ViewHolder,是以在這裡,我們需要實作onCreateViewHolder方法,其會傳回一個RecyclerView.ViewHolder對象。

  3. static class OrderListFooterHolder extends RecyclerView.ViewHolder
  4. static class OrderListViewHolder extends RecyclerView.ViewHolder

    既然上一步傳回了一個RecyclerView.ViewHolder對象,對應的,我們就要實作自己的ViewHolder,來存儲對應的元件了,如上面的OrderListFootHolder和OrderListViewHolder。

  5. public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position)

    有了ViewHolder之後,接下來就是要将ViewHolder和資料給綁定到一起來,則需要去調用OnBindViewHolder方法了,其參數一個為對應的ViewHolder,一個為對應的位置,通過此位置,去資料清單中擷取對應的資料。

  6. public int getItemCount()

    最後,我們還要實作getItemCount方法,告知RecycleView,此Adapter到底要處理多少個對象。

至此,對RecycleView的基本使用就可是這樣了。

繼續閱讀