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-

时间: 2024-07-30 19:22:44

RecyclerView的通用适配器的相关文章

让偷懒更彻底——用Butterknife 来为recyclerview 打造通用适配器(上)

背景 随着recyclerview 的越来越普及,其高度的易用性,让我们越来越爱不释手,当然网上也出现了很多类似的通用适配器,让我们更加方便的使用它,今天我们这里介绍一种新的recyclerview的通用适配器的实现思路--把recyclerview和ButterKnife结合起来使用(ps:因为公司开发一直使用butterknife,才有了这种想法). 首先贴上我的实现效果: 代码用法使用: ModelRecyclerAdapter adapter = new ModelRecyclerAda

RecyclerView的通用适配器的高级使用

前言 博主由于项目中频繁的使用了V7包中的RecyclerView来代替ListView的列表展示,所以抽空基于ListView的通用适配器的原理,给RecyclerView也写了一个通用适配器主要支持以下功能: 1.支持item的点击事件,在多布局的情况下可以指定生效的itemType 2.支持item中的控件的点击事件(博主觉得具有创新性),在多布局的情况下可以指定生效的itemType 3.支持添加和移除头部(博主没有写添加尾部的方法,其实和添加头部的方法是类似的,如果你有需要就自己参照着

RecyclerView通用适配器的实现

分析 我们需要在RecyclerViewAdapter内部维持一个数据集合的引用 需要实现Item的点击事件,包括短按和长按,并需要向外部提供设置监听器的方法 这个适配器必须通用,所以应该是泛型的,并且ViewHolder也是通用的,可以采用SparseArray维持View的所有集合 在RecyclerViewAdapter内部需要实现数据的绑定(抽象方法,延迟到子类实现),监听器的绑定 编写监听器 分为短按事件和长按事件 短按监听器 package cn.edu.zafu.base.adap

RecyclerView 的 RecyclerView.Adapter 通用版的实现

RecyclerView 的 RecyclerView.Adapter 通用版的实现(有加载更多的功能) Android5.0给我们带来了RecyclerView 他的灵活性非常强,可以替代Listview和GridView,本文主要说说他的适配器的使用,下面是自己封装的一个通用版的适配器(),废话不多说,看代码: //这个Adapter里面有两个抽象方法 public abstract class MyRecycleViewAdapter<T> extends RecyclerView.Ad

RecyclerView的万能适配器+定义可以到底部自动刷新的RecyclerView

RecyclerView的重要性就不做重复说明了,为了方便以后直接使用写了这个,主要有: 万能适配器在使用的时候分为定义布局和绑定数据,方便直接套用.加入了底部刷新,需要配合自己写的RecyclerView一起使用,对于布局中各个子布局和控件可以做到响应各种点击事件: 首先抽取ViewHolder:这里的要点是用到了SparseArray(源码中类似ArrayList.直接使用Object数组进行实现): package com.fightzhao.baseadapterdemo.base; i

Android 5.0 v7扩展包之RecyclerView的使用以及通用适配器的封装实现

添加Gradle依赖 compile 'com.android.support:appcompat-v7:23.2.1'compile 'com.android.support:recyclerview-v7:23.2.1' 备注:recyclerview的版本号要与appcompat的一致,此处为: v7:23.2.1 以泛型方式定义通用RecyclerViewHold对象,内部以SparseArray存储View对象,提高xml的解析速度. /** * Created by Administ

打造android偷懒神器———RecyclerView的万能适配器

转载请注明出处谢谢:http://www.cnblogs.com/liushilin/p/5720926.html 很不好意思让大家久等了,本来昨天就应该写这个的,无奈公司昨天任务比较紧,所以没能按时给大家带来RecyclerView的适配器,楼主对期待的小伙伴表示最深刻地歉意. 如果你没有看前面的万能的ListView,GridView等的万能适配器,楼主推荐你去看一看,当然,大牛就免了. 另外,楼主今天在构思这个RecyclerView的过程中发现前天写的ListView有点毛病,现在楼主已

使用通用适配器Base-adapter-helper

适配器写多了会有一种写到吐的感觉,今天来体验一下不用写适配器等待感觉,一般来说,我们写适配器都是重写getView方法,然后使用ViewHolder设计模式,在getView里进行数据绑定,写一次还好,写多了会感觉在不断做重复工作,那么有没有这么一个通用的适配器供我们使用,而不用写那么多次重复代码呢,答案是有的,见https://github.com/JoanZapata/base-adapter-helper,今天就使用一下这个适配器. 在这之前,先看下实现效果. 开始编写实体类,涉及到的就是

RecyclerView打造通用的万能Adapter

既然想做到通用那么现在摆在面前的就三个问题:数据怎么办?布局怎么办? 绑定怎么办?.数据决定采用泛型,布局打算直接构造传递,绑定显示效果肯定就只能回传. 1 基本改造 数据决定采用泛型,布局打算直接构造传递,绑定显示效果回传. 1 public abstract class CommonRecyclerAdapter<T> extends RecyclerView.Adapter<ViewHolder> { 2 3 protected Context mContext; 4 pro