欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android RecyclerView 數(shù)據(jù)綁定實例代碼

 更新時間:2016年09月07日 14:56:42   作者:lypeer  
本文主要介紹Android RecyclerView 數(shù)據(jù)綁定的資料,這里詳細說明如何實現(xiàn) Android RecyclerView的數(shù)據(jù)綁定,并附示例代碼,有需要的小伙伴可以參考下

前言

在上一個項目里有很多很多很多很多的RecyclerView,然后我需要寫很多很多很多很多的Adapter和Viewholder——多倒沒問題,但是里面有很多重復的代碼這就不能忍了!每一個Adapter和ViewHolder其實做的事情非常的像:視圖綁定,數(shù)據(jù)綁定,點擊事件分發(fā)。還有啥?既然它們做的事情都一樣,為啥我們還要傻傻的繼續(xù)寫著重復的代碼?

正文

BaseAdapter

通常我們要創(chuàng)建一個RecyclerView.Adapter是怎么做的?

  1. 接收一個數(shù)據(jù)列表
  2. 重寫getItemCount()方法,確定Item的個數(shù)
  3. 重寫onCreateViewHolder()方法,綁定Layout,新建一個我們自己寫的RecyclerView.ViewHolder
  4. 重寫onBindViewHolder()方法,進行數(shù)據(jù)和視圖綁定
  5. 由于RecyclerView沒有寫點擊事件,把點擊事件分發(fā)出去

基本上就是這個套路,或者再加一個refreshData()的方法——傳新的數(shù)據(jù)進來然后notifyDataSetChanged()?;谶@些點,我寫了一個BaseAdapter基類:


/**
 * Adapter基類.
 * 適用于只有單個Item的RecyclerView.
 *
 * Created by lypeer on 16-5-24.
 */
public abstract class BaseAdapter<V> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

 /**
  * 裝載了每個Item的Value的列表
  */
 private List<V> mValueList;

 /**
  * 我寫的一個接口,通過回調(diào)分發(fā)點擊事件
  */
 private OnItemClickListener<V> mOnItemClickListener;

 @Override
 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  return createViewHolder(parent.getContext(), parent);
 }

 @Override
 @SuppressWarnings("unchecked")//一定會是BaseViewHolder的子類,因為createViewHolder()的返回值
 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
  //BaseViewHolder是我抽象出來的RecyclerView.ViewHolder的基類,下面會有詳細講解
  ((BaseViewHolder) holder).setData(mValueList.get(position), position, mOnItemClickListener);
 }

 /**
  * 設置每個Item的點擊事件
  * @param listener
  */
 public void setOnClickListener(OnItemClickListener<V> listener) {
  this.mOnItemClickListener = listener;
 }

 /**
  * 刷新數(shù)據(jù)
  * @param valueList 新的數(shù)據(jù)列表
  */
 public void refreshData(List<V> valueList) {
  this.mValueList = valueList;
  notifyDataSetChanged();
 }

 @Override
 public int getItemCount() {
  return mValueList == null ? 0 : mValueList.size();
 }

 /**
  * 生成ViewHolder
  * @param context
  * @param parent
  * @return
  */
 protected abstract BaseViewHolder createViewHolder(Context context, ViewGroup parent);
}

它的子類在繼承它的時候需要指定泛型的具體類型,因為不同的Item也許其數(shù)據(jù)類型并不一樣,這樣就可以適應更多的Item。另外,其中提到了一個接口OnItemClickListener,這個接口很簡單:

/**
 * 點擊事件的接口
 * Created by lypeer on 16-5-24.
 */
public interface OnItemClickListener<V> {

 /**
  * 當item被點擊的時候進行事件分發(fā)
  *
  * @param itemValue 點擊的item傳遞的值
  * @param viewID 點擊控件的id
  * @param position 被點擊的item的位置
  */
 void onItemClick(V itemValue, int viewID, int position);
}

在使用它的時候同樣需要使用泛型——原因和上面一樣。

通過上面的BaseAdapter,我們把很多的共有操作都封裝在了基類里面,而它的子類只需要根據(jù)需要新建不同的ViewHolder就行了——當然,這個viewHolder必須繼承自BaseViewHolder,而BaseViewHolder是什么下面會有詳細講解。接下來是一個例子,假設我們現(xiàn)在在一個界面要有一個RecyclerView,它的每個Item的數(shù)據(jù)是一個String值,那么怎么使用我們的BaseAdapter簡化開發(fā)過程呢?

public class SampleAdapter extends BaseAdapter<String> {
 @Override
 protected BaseViewHolder createViewHolder(Context context, ViewGroup parent) {
  //SampleViewHolder繼承自BaseViewHolder
  return new SampleViewHolder(context, parent);
 }
}

是的,你沒有看錯!就只有這么幾行代碼!5秒完成!驚喜么?!

你只需要新建一個SampleAdapter繼承自BaseAdapter,然后指定其泛型為String,再return new SampleViewHolder(context, parent) , 就完成了整個操作。

但是,有些讀者也許會有疑惑:也許我們需要在SampleViewHolder里面做很多的操作呢?那豈不是只是把代碼轉換了一個地方而已,實質(zhì)上并沒有什么優(yōu)化之處。

然而并不是。

BaseViewHolder

我一直認為,將ViewHolder寫在Adapter里面是挺不明智的一個做法。這樣的話Adapter這個類的職責太重了,它做得事情太多了,從數(shù)據(jù)接收到界面綁定,從控件初始化到點擊事件分發(fā),它簡直什么都做完了。而這樣是很不好的。很輕易的,一個比較復雜的RecyclerView的Adapter的代碼就能達到成百上千行,這很可怕,這意味著這個類將變得冗雜且難以維護。那么怎么避免這種情況發(fā)生呢?我選擇了將ViewHolder分離,同時加重ViewHolder的職責,使它們能比較均衡。

直接看BaseViewHolder的代碼:

/**
 * ViewHolder基類
 * 
 * Created by lypeer on 16-5-27.
 */
public abstract class BaseViewHolder<V> extends RecyclerView.ViewHolder {

 public BaseViewHolder(Context context, ViewGroup root, int layoutRes) {
  super(LayoutInflater.from(context).inflate(layoutRes, root, false));
  //這里使用了ButterKnife來進行控件的綁定
  ButterKnife.bind(this, itemView);
 }

 /**
  * 方便其子類進行一些需要Context的操作.
  *
  * @return 調(diào)用者的Context
  */
 public Context getContext() {
  return itemView.getContext();
 }

 /**
  * 抽象方法,綁定數(shù)據(jù).
  * 讓子類自行對數(shù)據(jù)和view進行綁定
  *
  * @param itemValue Item的數(shù)據(jù)
  * @param position 當前item的position
  * @param listener 點擊事件監(jiān)聽者
  */
 protected abstract void bindData(V itemValue, int position, OnItemClickListener listener);

 /**
  * 用于傳遞數(shù)據(jù)和信息
  *
  * @param itemValue
  * @param position
  * @param listener
  */
 public void setData(V itemValue, int position, OnItemClickListener listener) {
  bindData(itemValue, position, listener);
 }
}

BaseViewHolder同樣采用了泛型,以適應不同的數(shù)據(jù)類型。同時,我在BaseViewHolder里面使用了ButterKnife來簡化代碼,從此再也不用反反復復的findViewById了。

另外,大家可以看到BaseViewHolder里面的構造方法中傳入了三個參數(shù),但是在上面BaseAdapter的例子里面SampleViewHolder的構造方法我們卻只傳入了它的前兩個構造參數(shù),而第三個參數(shù)layoutRes并沒有傳進去,這是怎么回事呢?是上面寫錯了么?當然不是。BaseViewHolder的構造方法中有三個傳參是因為它需要三個傳參,而它的子類只有兩個傳參是因為它只能有兩個傳參。_BaseViewHolder必須要滿足它的super構造,所以必須要有那三個參數(shù),而它的子類如果那三個參數(shù)都是由外界傳進來的,那么它怎么進行針對那個布局進行特異化的操作?它必須在類里面顯式的指定Layout ID_——這其實是我很想優(yōu)化的一個地方,因為這樣的話子類繼承BaseViewHolder之后還要修改它的構造方法,這是比較讓人不省心的,但是目前還沒有想到什么好點子來優(yōu)雅地優(yōu)化它。

BaseViewHolder里面有兩個看起來很像的方法:setData()和bindData(),然而實際上除了傳參相同,它們其他方面根本完全不一樣。setData()方法是一個public的方法,可以由BaseViewHolder的子類的對象調(diào)用,其作用是從外部傳入數(shù)據(jù),以供ViewHolder所hold的那個view初始化,它可以說是一座傳輸信息的橋梁;而getData()是一個抽象的方法,它的具體實現(xiàn)在每一個BaseViewHolder的子類中,這些子類在這個方法里面進行控件的綁定和初始化,以及對控件的點擊事件的處理等等。

說到點擊事件的處理,它的子類應該怎么完成這件事呢?通過OnItemClickListener。我們可以借助于OnItemClickListener的接口回調(diào)來將需要處理的點擊事件傳遞到外界,然后由外界進行處理。那么如果有多個控件的點擊事件需要處理怎么辦?不用擔心,因為在OnItemClickListener的onClick方法中你需要傳入點擊的控件的id,這樣一來就可以在外界進行對傳入id的判斷,從而針對不同的id執(zhí)行不同的點擊事件了。

接下來通過一個例子來看下具體怎么用,就是上面的那個SampleViewHolder吧:

public class SampleViewHolder extends BaseViewHolder<String> {

 //一個普通的可點擊的TextView
 @Bind(R.id.is_tv_content)
 TextView mIsTvContent;

 public SampleViewHolder(Context context, ViewGroup root) {
  //修改了構造方法,在這里顯式指定Layout ID
  super(context, root, R.layout.item_sample);
 }

 @Override
 protected void bindData(final String itemValue, final int position, final OnItemClickListener listener) {
  //在這里完成控件的初始化,將其與數(shù)據(jù)綁定
  if (itemValue != null) {
   mIsTvContent.setText(itemValue);
  }
  //如果需要有點擊事件,就通過listener把它傳遞出去
  mIsTvContent.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    //如果外界沒有調(diào)用BaseAdapter.setOnClickListener(),
    //listener就為null
    if(listener == null){
     return;
    }
    //listener不為null就將這個事件傳遞給外界處理
    listener.onItemClick(itemValue , v.getId() , position);
   }
  });
 }
}

同樣很簡單方便快捷清晰。但是還是有幾點值得注意的地方。首先,不能忘了修改構造方法,顯式的在super里面指定Layout ID,不然下一步都沒法做,那就懵逼了。另外,在調(diào)用listener.onClick()方法的時候必須進行l(wèi)istener的驗空——因為listener真的有可能為空!這樣的話非常容易產(chǎn)生空異常導致程序崩潰。

賓果,就這樣,SampleViewHolder就完成了,同樣幾乎不費吹灰之力。

結語

這篇博文的目的是分享一些我總結出來的東西,希望能讓大家的開發(fā)加速那么一點點。當然,這里面也許還有我沒發(fā)現(xiàn)的bug什么的,如果大家在使用的過程中發(fā)現(xiàn)了問題請不要客氣,狠狠地砸給我吧!

最后還是再總結一下在有了BaseAdapter和BaseViewHolder的情況下怎么最快的搞定RecyclerView的那一套:

ViewHolder相關
新建 XXXViewHolder 繼承自BaseViewHolder,指定泛型類型(也就是Item中數(shù)據(jù)的數(shù)據(jù)類型)。
刪掉構造方法中的layoutRes參數(shù),在super里面顯式指定Layout ID。
用ButterKnife綁定控件。
在bindData()方法中完成控件的初始化以及點擊事件的傳遞(別忘了listener的驗空)

Adapter相關

新建 XXXAdapter 繼承自BaseAdapter,指定泛型類型(也就是Item中數(shù)據(jù)的數(shù)據(jù)類型)。
return new XXXViewHolder(context, parent);

外界相關

綁定RecyclerView,新建XXXAdapter。
調(diào)用 BaseAdapter.refreshData()方法傳入數(shù)據(jù)列表。
如果有對點擊事件處理的需求,則調(diào)用BaseAdapter.setOnClickListener()方法。

目前我只做了針對RecyclerView中單個的Item的BaseAdapter,但是BaseViewHolder使可以通用的,并且其在多Item下也可以大大的簡化Adapter的體積。

以上就是對Android RecyclerView 數(shù)據(jù)綁定的資料整理,后續(xù)繼續(xù)補充相關資料謝謝大家對本站的支持!

相關文章

  • android截圖事件監(jiān)聽的原理與實現(xiàn)

    android截圖事件監(jiān)聽的原理與實現(xiàn)

    本篇文章主要介紹了android截圖事件監(jiān)聽的原理與實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • Android使用Retrofit實現(xiàn)自定義Converter解析接口流程詳解

    Android使用Retrofit實現(xiàn)自定義Converter解析接口流程詳解

    Retrofit是一個RESTful的HTTP網(wǎng)絡請求框架的封裝,網(wǎng)絡請求的工作本質(zhì)上是OkHttp完成,而Retrofit僅負責網(wǎng)絡請求接口的封裝
    2023-03-03
  • Android 讀取sdcard上的圖片實例(必看)

    Android 讀取sdcard上的圖片實例(必看)

    下面小編就為大家?guī)硪黄狝ndroid 讀取sdcard上的圖片實例(必看)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • Android四大組件之Activity詳細介紹

    Android四大組件之Activity詳細介紹

    大家好,本篇文章主要講的是Android四大組件之Activity詳解,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • Android實現(xiàn)注冊界面

    Android實現(xiàn)注冊界面

    這篇文章主要為大家詳細介紹了Android實現(xiàn)注冊界面,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Android Studio報錯unable to access android sdk add-on list解決方案

    Android Studio報錯unable to access android sdk add-on list解決方案

    這篇文章主要介紹了Android Studio報錯unable to access android sdk add-on list解決方案,本文通過多種方式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • Android PopupWindow實現(xiàn)左側彈窗效果

    Android PopupWindow實現(xiàn)左側彈窗效果

    這篇文章主要為大家詳細介紹了Android PopupWindow實現(xiàn)左側彈窗效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Android 設置Edittext獲取焦點并彈出軟鍵盤

    Android 設置Edittext獲取焦點并彈出軟鍵盤

    本文主要介紹了Android設置Edittext獲取焦點并彈出軟鍵盤的實現(xiàn)代碼。具有很好的參考價值。下面跟著小編一起來看下吧
    2017-04-04
  • Android編程中的5種數(shù)據(jù)存儲方式

    Android編程中的5種數(shù)據(jù)存儲方式

    這篇文章主要介紹了Android編程中的5種數(shù)據(jù)存儲方式,結合實例形式詳細分析了Android實現(xiàn)數(shù)據(jù)存儲的5中實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-12-12
  • Android將Glide動態(tài)加載不同大小的圖片切圓角與圓形的方法

    Android將Glide動態(tài)加載不同大小的圖片切圓角與圓形的方法

    這篇文章主要給大家介紹了關于Android如何將Glide動態(tài)加載不同大小的圖片切圓角與圓形的方法,文中通過示例代碼介紹的非常吸納關系,對各位Android開發(fā)者們具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧。
    2017-11-11

最新評論