zoukankan      html  css  js  c++  java
  • 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-

  • 相关阅读:
    python目录操作【os和os.path】
    Zabbix4.0 zabbix 快速监控主机
    Zabbix 4.0 钉钉报警
    MySql:sql99语法的连接查询
    bat脚本中存在多条指令,但只执行到某条指令不继续向下执行的一种解决方法
    基类与接口类中的虚析构函数(virtual destructor)
    TortoiseGit使用指南;
    Rust编译问题Blocking waiting for file lock on package cache
    win10安装visual C++ 6.0,在最后显示安装程序正在更新您的系统,然后就无响应
    从实现装饰者模式中思考C++指针和引用的选择
  • 原文地址:https://www.cnblogs.com/huangjialin/p/7808599.html
Copyright © 2011-2022 走看看