RecyclerView的通用適配器


本來這一個主題應該早就寫了,只是項目多,屬於自己的時間不多,所以現在才開動!!

前一段時間寫了一篇文章,是關於ListView,GriView萬能適配器,沒有看過的同學,可以先看看那篇文章,然后在來學習RecyclerView的話,會容易很多。鏈接http://www.cnblogs.com/huangjialin/p/7661328.html

當然,如果對RecyclerView基礎不是了解的朋友,建議先去熟悉一下RecyclerView的基礎知識!

閑話不多說,先簡單的介紹一下這個RecyclerView,它是Android5.0的時候出來的一個新控件,主要目的就是替代ListView和GridView,也就是說RecyclerView能夠實現ListView和GridView的效果,甚至比原來的更好,更方便,

我們知道,在寫ListView和GridView的時候,都需要寫一個適配器,然后繼承BaseAdapter,接着實現幾個方法,套路都是一樣的,但是前一段時間寫了一個通用的適配器,所以在寫ListView和GridView的adapter的時候,可以省了很多事,方便了許多,那么,問題來了,

RecyclerView的通用適配器怎么寫呢???

我們知道,在寫ListView和GridView的適配器時候,我們需要考慮view的復用機制,但是RecyclerView內部已經幫我們寫好了復用機制,所以,我們不需要考慮復用的情況,先不說,從ViewHolder開始

 

通用ViewHoler

 

 1 package com.xiaoma.xting.adapter;
 2 
 3 import android.content.Context;
 4 import android.support.v7.widget.RecyclerView;
 5 import android.util.SparseArray;
 6 import android.view.LayoutInflater;
 7 import android.view.View;
 8 import android.view.ViewGroup;
 9 import android.widget.ImageView;
10 import android.widget.TextView;
11 
12 /**
13  * Created by Administrator on 2017/11/6 0006.
14  * huangjialin
15  */
16 
17 public class BaseViewHolder extends RecyclerView.ViewHolder {
18     private SparseArray<View> mViews; //用來存儲控件
19     private View mConvertView;
20     private Context mContext;
21 
22 
23     public BaseViewHolder(Context context, View itemView) {
24         super(itemView);
25         this.mContext = context;
26         mConvertView = itemView;
27         mViews = new SparseArray<View>();
28     }
29 
30 
31     /**
32      * 提供一個獲取ViewHolder的方法
33      */
34     public static BaseViewHolder getRecyclerHolder(Context context, ViewGroup parent, int layoutId) {
35         View itemView = LayoutInflater.from(context).inflate(layoutId, parent, false);
36         BaseViewHolder viewHolder = new BaseViewHolder(context, itemView);
37         return viewHolder;
38     }
39 
40 
41     /**
42      * 獲取控件
43      */
44     public <T extends View> T getView(int viewId) {
45         View view = mViews.get(viewId);
46         if (view == null) {
47             view = mConvertView.findViewById(viewId);
48             mViews.put(viewId, view);
49         }
50         return (T) view;
51     }
52 
53 
54     /**
55      * 給TextView設置setText方法
56      */
57     public BaseViewHolder setText(int viewId, String text) {
58         TextView tv = getView(viewId);
59         tv.setText(text);
60         return this;
61     }
62 
63 
64     /**
65      * 給ImageView設置setImageResource方法
66      */
67     public BaseViewHolder setImageResource(int viewId, int resId) {
68         ImageView view = getView(viewId);
69         view.setImageResource(resId);
70         return this;
71     }
72 
73     /**
74      * 添加點擊事件
75      */
76     public BaseViewHolder setOnClickListener(int viewId, View.OnClickListener listener) {
77         View view = getView(viewId);
78         view.setOnClickListener(listener);
79         return this;
80     }
81 }

 

代碼中,創建了BaseViewHolder,並且繼承RecyclerView的ViewHoler,我們對外提供兩個方法,一個是獲取viewholder的getRecyclerHolder()方法,另一個是獲取控件的getView()方法,由於RecyclerView的保存控件的方式是以變量的形式來,而這里則是通過SparseArray來通過key來進行存儲的。

 

通用適配器

前面viewholer,現在看看adapter,先上代碼

 1 package com.example.administrator.recylerviewadaptertest;
 2 
 3 import android.content.Context;
 4 import android.support.v7.widget.RecyclerView;
 5 import android.view.ViewGroup;
 6 
 7 import java.util.List;
 8 
 9 /**
10  * Created by Administrator on 2017/11/6 0006.
11  * huangjialin
12  * 普通類型的適配器
13  */
14 
15 public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> {
16     private Context mContext;
17     private int mLayoutId;
18     private List<T> mData;
19 
20 
21     public BaseRecyclerAdapter(Context mContext, int mLayoutId, List<T> mData) {
22         this.mContext = mContext;
23         this.mLayoutId = mLayoutId;
24         this.mData = mData;
25     }
26 
27     @Override
28     public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
29         BaseViewHolder viewHolder = BaseViewHolder.getRecyclerHolder(mContext, parent, mLayoutId);
30         return viewHolder;
31     }
32 
33     @Override
34     public void onBindViewHolder(BaseViewHolder holder, int position) {
35         convert(holder, mData.get(position));
36 
37     }
38 
39     @Override
40     public int getItemCount() {
41         return mData.size();
42     }
43 
44     /**
45      * 對外提供的方法
46      */
47     public abstract void convert(BaseViewHolder holder, T t);
48 
49 }

代碼不多,也相對簡單,在onCreateViewHolder()方法中,獲取到viewholer,然后我們自己定義一個convert()方法,對外提供該方法。那么,我們怎么用呢?

 1 package com.example.administrator.recylerviewadaptertest;
 2 
 3 import android.app.Activity;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.os.Bundle;
 6 import android.support.v7.widget.LinearLayoutManager;
 7 import android.support.v7.widget.RecyclerView;
 8 import android.widget.TextView;
 9 
10 import java.util.ArrayList;
11 import java.util.List;
12 
13 public class MainActivity extends Activity {
14     private RecyclerView recycler;
15     private BaseRecyclerAdapter mAdapter;
16     private List<String> stringList = new ArrayList<String>();
17 
18     @Override
19     protected void onCreate(Bundle savedInstanceState) {
20         super.onCreate(savedInstanceState);
21         setContentView(R.layout.activity_main);
22 
23         recycler = findViewById(R.id.recycler);
24 
25         mAdapter = new BaseRecyclerAdapter<String>(this, R.layout.rl_item_view, stringList) {
26             @Override
27             public void convert(BaseViewHolder holder, String s) {
28                 holder.setText(R.id.test, s);
29             }
30         };
31 
32         LinearLayoutManager manager = new LinearLayoutManager(this);
33         recycler.setLayoutManager(manager);
34         recycler.setAdapter(mAdapter);
35 
36 
37         for (int i = 0; i < 50; i++) {
38             stringList.add("測試-->" + i);
39         }
40         mAdapter.notifyDataSetChanged();
41 
42 
43     }
44 }

這些都相對來說很簡單如果有朋友覺得看不懂的話,我強烈建議先去看一下前面寫的ListView通用適配器,然后回來你就會發現很簡單了,套路都是差不多。

 

ItemViewType

 

前面寫的相對來說是針對與一些常見的列表布局,如果說復雜一些的布局,可能就行不通了,比如說我一個列表第一個item垂直顯示若干個控件,第二個item我水平顯示若干個控件,按照以往的經驗,我們通常會
在adapter中實現getItemViewType()方法,然后進行一些判斷,但是通用適配器中改怎么實現呢??
從前面獲取viewholder的時候,我們知道viewholder是通過布局來id來進行獲取的,那么,我們能不能這樣寫呢,我們通過不同的布局,來獲取不同的viewholder呢
我們在BaseRecyclerAdapter中加上這個接口

1  /**
2      * 針對多種類型的itemView
3      * @param <T>
4      */
5     public interface ConmonItemType<T> {
6         int getLayoutId(int itemType); //不同的Item的布局
7 
8         int getItemViewType(int position, T t); //type
9     }

然后我們新創建一個adapter並且繼承BaseRecyclerAdapter,代碼:

 1 package com.example.administrator.recylerviewadaptertest;
 2 
 3 import android.content.Context;
 4 import android.view.ViewGroup;
 5 
 6 import java.util.List;
 7 
 8 /**
 9  * Created by Administrator on 2017/11/6 0006.
10  * huangjialin
11  * 如果列表的布局item有多種類型,則需要繼承該適配器
12  */
13 
14 public abstract class MultiItemCommonAdapter<T> extends BaseRecyclerAdapter<T> {
15     private ConmonItemType<T> mConmonItemType;
16     private List<T> mDatas;
17     private Context mContext;
18 
19 
20     public MultiItemCommonAdapter(Context mContext, List<T> mData, ConmonItemType<T> conmonItemType) {
21         super(mContext, -1, mData);
22         this.mConmonItemType = conmonItemType;
23         mDatas = mData;
24         this.mContext = mContext;
25     }
26 
27     @Override
28     public int getItemViewType(int position) {
29         return mConmonItemType.getItemViewType(position, mDatas.get(position));
30     }
31 
32 
33     @Override
34     public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
35         int layoutId = mConmonItemType.getLayoutId(viewType);
36         BaseViewHolder holder = BaseViewHolder.getRecyclerHolder(mContext, parent, layoutId);
37         return holder;
38     }
39 }

從代碼可以看出,我們通過構造方法從外面傳進來的ConmonItemType<T> conmonItemType,通過這個來獲取不同的布局,從而獲取到不同的viewholer,看看怎么使用:

 1 package com.example.administrator.recylerviewadaptertest;
 2 
 3 import android.app.Activity;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.os.Bundle;
 6 import android.support.v7.widget.LinearLayoutManager;
 7 import android.support.v7.widget.RecyclerView;
 8 import android.util.Log;
 9 import android.widget.TextView;
10 
11 import java.util.ArrayList;
12 import java.util.List;
13 
14 public class MainActivity extends Activity {
15     private RecyclerView recycler;
16     private BaseRecyclerAdapter mAdapter;
17     private List<String> stringList = new ArrayList<String>();
18 
19 
20     private MultiItemCommonAdapter adapter;
21     private int typeOne = 1;
22     private int typeTwo = 2;
23 
24     @Override
25     protected void onCreate(Bundle savedInstanceState) {
26         super.onCreate(savedInstanceState);
27         setContentView(R.layout.activity_main);
28 
29         recycler = findViewById(R.id.recycler);
30 
31         /**
32          * 普通的列表形式
33          */
34 //        mAdapter = new BaseRecyclerAdapter<String>(this, R.layout.rl_item_view, stringList) {
35 //            @Override
36 //            public void convert(BaseViewHolder holder, String s) {
37 //                holder.setText(R.id.test, s);
38 //            }
39 //        };
40 //
41 //        LinearLayoutManager manager = new LinearLayoutManager(this);
42 //        recycler.setLayoutManager(manager);
43 //        recycler.setAdapter(mAdapter);
44 //
45 //
46 //        for (int i = 0; i < 50; i++) {
47 //            stringList.add("測試-->" + i);
48 //        }
49 //        mAdapter.notifyDataSetChanged();
50 
51 
52         /**
53          * 不同item布局的形式
54          */
55         BaseRecyclerAdapter.ConmonItemType conmonItemType = new BaseRecyclerAdapter.ConmonItemType<String>() {
56 
57             @Override
58             public int getLayoutId(int itemType) {
59                 if (itemType == typeOne) {
60                     return R.layout.item_one;
61                 } else {
62                     return R.layout.item_two;
63                 }
64             }
65 
66             @Override
67             public int getItemViewType(int position, String s) {
68                 if (position == 0) {
69                     return typeOne;
70                 } else {
71                     return typeTwo;
72                 }
73             }
74         };
75 
76 
77         for (int i = 0; i < 2; i++) {
78             stringList.add("測試-->" + i);
79         }
80 
81 
82         adapter = new MultiItemCommonAdapter<String>(this, stringList, conmonItemType) {
83             @Override
84             public void convert(BaseViewHolder holder, String s) {
85                 if (holder.getItemViewType() == 0) {
86                     //Todo
87 
88                 } else {
89                     //Todo
90                 }
91             }
92         };
93         LinearLayoutManager manager = new LinearLayoutManager(this);
94         recycler.setLayoutManager(manager);
95         recycler.setAdapter(adapter);
96 
97     }
98 }

在這里我是自己定義的typeone,和typetwo,在項目中我們可以根據bean來進行判斷,不同的類型,返回不同的值,從而獲取不同的item布局,ok,這樣的話,我們的多種ItemViewType的支持也就完成了

源碼鏈接:https://github.com/343661629/RecyclerView-

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM