从头開始学 RecyclerView(三) 封装简化
前言
上一篇的代码,也是基于这些封装的。 
RV的封装,跟曾经的listView之类的封装,大同小异。 
这里,从@devwiki 处,将代码搬过来。基本无改动
BaseHolder的优化
- 使ViewHolder仅仅用来缓存View。
- 加入SparseArray,使之来缓存View。
- 加入BaseHolder(View view)构造器,外部更方便控制View。
- 保留getContext()方法,方便获取Context对象。
- getView(resid)。简化itemView.findviewById()
/**
 * from http://blog.devwiki.net/index.php/2016/07/17/Recycler-View-Adapter-ViewHolder-optimized.html
 * 基础的ViewHolder</br>
 * ViewHolder仅仅作View的缓存,不关心数据内容
 * Created by DevWiki on 2016/5/17.
 */
public class BaseHolder extends RecyclerView.ViewHolder {
    private SparseArray<View> mViewArray;
    /**
     * 构造ViewHolder  (该方法涉及到parent,不经常使用)
     * @param parent 父类容器
     * @param resId 布局资源文件id
     */
    public BaseHolder(ViewGroup parent, @LayoutRes int resId) {
        super(LayoutInflater.from(parent.getContext()).inflate(resId, parent, false));
        mViewArray = new SparseArray<>();
    }
    /**
     * 构造ViewHolder
     * @param context
     * @param resId 布局资源文件id
     */
    public BaseHolder(Context context, @LayoutRes int resId) {
        super(LayoutInflater.from(context).inflate(resId, null, false));
        mViewArray = new SparseArray<>();
    }
    /**
     * 构建ViewHolder
     * @param view 布局View
     */
    public BaseHolder(View view) {
        super(view);
        mViewArray = new SparseArray<>();
    }
    /**
     * 获取布局中的View
     * @param viewId view的Id
     * @param <T> View的类型
     * @return view
     */
    public <T extends View> T getView(@IdRes int viewId){
        View view = mViewArray.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            mViewArray.put(viewId, view);
        }
        return (T) view;
    }
    /**
     * 获取Context实例
     * @return context
     */
    public Context getContext() {
        return itemView.getContext();
    }
}Adapter部分的优化
Adapter拆分为两个抽象类:AbsAdapter与BaseAdapter,当中: 
AbsAdapter:封装了和ViewHolder和HeaderView。FooterView相关的方法。 
BaseAdapter:继承AbsAdapter。封装了数据相关的方法。 
各自聚焦于不同的方面,方面日后扩展。
AbsAdapter的代码例如以下:
/**
 * from http://blog.devwiki.net/index.php/2016/07/17/Recycler-View-Adapter-ViewHolder-optimized.html
 * RecyclerView.Adapter的扩展,包括headerView/footerView等
 * Created by DevWiki on 2016/7/13.
 */
public abstract class AbsAdapter<VH extends BaseHolder> extends RecyclerView.Adapter<BaseHolder> {
    private static final String TAG = "AbsAdapter";
    public static final int VIEW_TYPE_HEADER = 1024;
    public static final int VIEW_TYPE_FOOTER = 1025;
    protected View headerView;
    protected View footerView;
    protected Context context;
    public AbsAdapter(Context context) {
        this.context = context;
    }
    @Override
    public final BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == VIEW_TYPE_HEADER) {
            return new BaseHolder(headerView);
        } else if (viewType == VIEW_TYPE_FOOTER) {
            return new BaseHolder(footerView);
        } else {
            return createCustomViewHolder(parent, viewType);
        }
    }
    /**
     * 创建自己定义的ViewHolder
     *
     * @param parent 父类容器
     * @param viewType view类型{@link #getItemViewType(int)}
     * @return ViewHolder
     */
    public abstract VH createCustomViewHolder(ViewGroup parent, int viewType);
    @Override
    public final void onBindViewHolder(BaseHolder holder, int position) {
        switch (holder.getItemViewType()) {
            case VIEW_TYPE_HEADER:
            case VIEW_TYPE_FOOTER:
                break;
            default:
                bindCustomViewHolder((VH) holder, position);
                break;
        }
    }
    @Override
    public void onBindViewHolder(BaseHolder holder, int position, List<Object> payloads) {
        super.onBindViewHolder(holder, position, payloads);
    }
    /**
     * 绑定自己定义的ViewHolder
     *
     * @param holder ViewHolder
     * @param position 位置
     */
    public abstract void bindCustomViewHolder(VH holder, int position);
    /**
     * 加入HeaderView
     *
     * @param headerView 顶部View对象
     */
    public void addHeaderView(View headerView) {
        if (headerView == null) {
            Log.w(TAG, "add the header view is null");
            return ;
        }
        this.headerView = headerView;
        notifyDataSetChanged();
    }
    /**
     * 移除HeaderView
     */
    public void removeHeaderView() {
        if (headerView != null) {
            headerView = null;
            notifyDataSetChanged();
        }
    }
    /**
     * 加入FooterView
     *
     * @param footerView View对象
     */
    public void addFooterView(View footerView) {
        if (footerView == null) {
            Log.w(TAG, "add the footer view is null");
            return;
        }
        this.footerView = footerView;
        notifyDataSetChanged();
    }
    /**
     * 移除FooterView
     */
    public void removeFooterView() {
        if (footerView != null) {
            footerView = null;
            notifyDataSetChanged();
        }
    }
    /**
     * 获取附加View的数量,包括HeaderView和FooterView
     *
     * @return 数量
     */
    public int getExtraViewCount() {
        int extraViewCount = 0;
        if (headerView != null) {
            extraViewCount++;
        }
        if (footerView != null) {
            extraViewCount++;
        }
        return extraViewCount;
    }
    /**
     * 获取顶部附加View数量,即HeaderView数量
     * @return 数量
     */
    public int getHeaderExtraViewCount() {
        return headerView == null ? 0 : 1;
    }
    /**
     * 获取底部附加View数量,即FooterView数量
     * @return 数量,0或1
     */
    public int getFooterExtraViewCount() {
        return footerView == null ?
0 : 1;
    }
    @Override
    public abstract long getItemId(int position);
}BaseAdapter的代码例如以下:
/**
 * from http://blog.devwiki.net/index.php/2016/07/17/Recycler-View-Adapter-ViewHolder-optimized.html
 * 基础的Adapter
 *
 * Created by DevWiki on 2016/7/13.
 */
public abstract class BaseAdapter<M, VH extends BaseHolder> extends AbsAdapter<VH> {
    private List<M> dataList;
    public BaseAdapter(Context context) {
        super(context);
        this.dataList = new ArrayList<>();
    }
    public BaseAdapter(Context context, List<M> list) {
        super(context);
        this.dataList = new ArrayList<>();
        this.dataList.addAll(list);
    }
    /**
     * 填充数据,此操作会清除原来的数据
     *
     * @param list 要填充的数据
     * @return true:填充成功并调用刷新数据
     */
    public boolean fillList(List<M> list) {
        dataList.clear();
        boolean result = dataList.addAll(list);
        if (result) {
            notifyDataSetChanged();
        }
        return result;
    }
    /**
     * 追加一条数据
     *
     * @param data 要追加的数据
     * @return true:追加成功并刷新界面
     */
    public boolean appendItem(M data) {
        boolean result = dataList.add(data);
        if (result) {
            if (getHeaderExtraViewCount() == 0) {
                notifyItemInserted(dataList.size() - 1);
            } else {
                notifyItemInserted(dataList.size());
            }
        }
        return result;
    }
    /**
     * 追加集合数据
     *
     * @param list 要追加的集合数据
     * @return 追加成功并刷新
     */
    public boolean appendList(List<M> list) {
        boolean result = dataList.addAll(list);
        if (result) {
            notifyDataSetChanged();
        }
        return result;
    }
    /**
     * 在最顶部前置数据
     *
     * @param data 要前置的数据
     */
    public void proposeItem(M data) {
        dataList.add(0, data);
        if (getHeaderExtraViewCount() == 0) {
            notifyItemInserted(0);
        } else {
            notifyItemInserted(getHeaderExtraViewCount());
        }
    }
    /**
     * 在顶部前置数据集合
     *
     * @param list 要前置的数据集合
     */
    public void proposeList(List<M> list) {
        dataList.addAll(0, list);
        notifyDataSetChanged();
    }
    @Override
    public long getItemId(int position) {
        return position;
    }
    @Override
    public final int getItemViewType(int position) {
        if (headerView != null && position == 0) {
            return VIEW_TYPE_HEADER;
        } else if (footerView != null && position == dataList.size() + getHeaderExtraViewCount()) {
            return VIEW_TYPE_FOOTER;
        } else {
            return getCustomViewType(position);
        }
    }
    /**
     * 获取自己定义View的类型
     *
     * @param position 位置
     * @return View的类型
     */
    public abstract int getCustomViewType(int position);
    @Override
    public int getItemCount() {
        return dataList.size() + getExtraViewCount();
    }
    /**
     * 依据位置获取一条数据
     *
     * @param position View的位置
     * @return 数据
     */
    public M getItem(int position) {
        if (headerView != null && position == 0
                || position >= dataList.size() + getHeaderExtraViewCount()) {
            return null;
        }
        return headerView == null ?
dataList.get(position) : dataList.get(position - 1);
    }
    /**
     * 依据ViewHolder获取数据
     *
     * @param holder ViewHolder
     * @return 数据
     */
    public M getItem(VH holder) {
        return getItem(holder.getAdapterPosition());
    }
    public void updateItem(M data) {
        int index = dataList.indexOf(data);
        if (index < 0) {
            return;
        }
        dataList.set(index, data);
        if (headerView == null) {
            notifyItemChanged(index);
        } else {
            notifyItemChanged(index + 1);
        }
    }
    /**
     * 移除一条数据
     *
     * @param position 位置
     */
    public void removeItem(int position) {
        if (headerView == null) {
            dataList.remove(position);
        } else {
            dataList.remove(position - 1);
        }
        notifyItemRemoved(position);
    }
    /**
     * 移除一条数据
     *
     * @param data 要移除的数据
     */
    public void removeItem(M data) {
        int index = dataList.indexOf(data);
        if (index < 0) {
            return;
        }
        dataList.remove(index);
        if (headerView == null) {
            notifyItemRemoved(index);
        } else {
            notifyItemRemoved(index + 1);
        }
    }
}參考
http://blog.devwiki.net/index.php/2016/07/17/Recycler-View-Adapter-ViewHolder-optimized.html 《RecyclerView的ViewHolder和Adapter的封装优化》
从头開始学 RecyclerView(三) 封装简化的更多相关文章
- 从头開始学 RecyclerView(六) LayoutManager
		前言 在前面的文章中.每一个演示样例,都使用了LayoutManager,毕竟它是RecyclerView必不可少的一部分. LayoutManager,顾名思义,就是『布局管理器』. 使用例如以下代 ... 
- [php learn] php 从头開始学习1
		前言:大概在2006年的时候,学习过一段时间的php.而且当时做了一个下载的站点,后来因为读研究生阶段用的是java.j2ee相关,所以php就搁浅掉了,php这些年也发生了非常大的变化,最大一个变化 ... 
- 送给刚刚開始学cocos2d-x引擎 移植Android的同学
		刚刚開始学cocos2-x,不过依照教程把已经安了一般Android的开发环境的eclipse又一次升级到安装好cdt和ndk就花了我几十小时,差点都要放弃了. 參考博客 http://blog.cs ... 
- 从零開始学Swift之Hello World进化版
		上节课,也就是昨晚啦,我们学习到从零開始学Swift之Hello World.那一节仅仅有一句代码,大家会认为不够过瘾. 那么这节课,就给大家来多点瘾货吧! 先上图! //var 代表变量的类型, s ... 
- 关东升的《从零開始学Swift》即将出版
		大家好: 苹果2015WWDC大会公布了Swift2.0,它较之前的版本号Swift1.x有非常大的变化.所以我即将出版<从零開始学Swift><从零開始学Swift>将在&l ... 
- 《PHP 5.5从零開始学(视频教学版)》内容简单介绍、文件夹
		<PHP 5.5从零開始学(视频教学版)>当当网购买地址: http://product.dangdang.com/23586810.html <PHP 5.5从零開始学(视频教学版 ... 
- 从零開始学android<数据存储(1)SharedPreferences属性文件.三十五.>
		在android中有五种保存数据的方法.各自是: Shared Preferences Store private primitive data in key-value pairs. 相应属性的键值 ... 
- 【高德地图API】从零開始学高德JS API(五)路线规划——驾车|公交|步行
		先来看两个问题:路线规划与导航有什么差别?步行导航与驾车导航有什么差别? 回答: 1.路线规划,指的是为用户提供3条路线推荐.[高德]在提供路线规划的时候,会提供用户自己定义路线规划功能,这是别家没有 ... 
- 第13章、布局Layouts之RelativeLayout相对布局(从零開始学Android)
		RelativeLayout相对布局 RelativeLayout是一种相对布局,控件的位置是依照相对位置来计算的,后一个控件在什么位置依赖于前一个控件的基本位置,是布局最经常使用,也是最灵活的一种布 ... 
随机推荐
- Java多线程中join方法的理解
			thread.Join把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的Join()方法,直到线程A执行完毕后,才会继续执行线程B. t.join( ... 
- 在SQLite中使用事务
			使用SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction() 方法时会检查事务的标志是否为成功,如果为成功则提交事务,否则回滚 ... 
- Asp.Net Mvc Action过滤器(二)
			在Mvc中为Action添加过滤器,有两种方式, 一.使用ActionFilterAttribute,简单方式,同时支持Result的过滤处理, 1.可以为空,支持的重写:OnActionExecut ... 
- [转]Infobright是一个与MySQL集成的开源数据仓库
			[文章作者:张宴 本文版本:v1.1 最后修改:2010.05.18 转载请注明原文链接:http://blog.zyan.cc/infobright/] Infobright是一个与MySQL集成的 ... 
- 【转】Mysql行转换为列
			From : http://www.cnblogs.com/lhj588/archive/2012/06/15/2550392.html# 今晚需要统计数据生成简易报表,由原表格数据是单行的形式,最好 ... 
- [转]分析MySQL数据类型的长度【mysql数据字段 中length和decimals的作用!熟悉mysql必看】
			转载自:http://blog.csdn.net/daydreamingboy/article/details/6310907 分析MySQL数据类型的长度 MySQL有几种数据类型可以限制类型的&q ... 
- 【deep learning学习笔记】注释yusugomori的DA代码 --- dA.cpp -- 训练
			说实话,具体的训练公式,我没有自己推导,姑且认为他写的代码是对的.总体上看,用bp的方法.特殊之处,在于输入层和输出层是完完全全的“同一层”. void dA::get_corrupted_input ... 
- COCO数据集深入理解
			TensorExpand/TensorExpand/Object detection/Data_interface/MSCOCO/ 深度学习数据集介绍及相互转换 Object segmentation ... 
- ORM数据库框架 SQLite 常用数据库框架比较 MD
			Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ... 
- JavaScript递归方法 生成 json tree 树形结构数据
			//递归方法 生成 json tree 数据 var getJsonTree = function(data, parentId) { var itemArr = []; for (var i = 0 ... 
