• 从头開始学 RecyclerView(三) 封装简化


    前言


    上一篇的代码,也是基于这些封装的。
    RV的封装,跟曾经的listView之类的封装,大同小异。
    这里,从@devwiki 处,将代码搬过来。基本无改动

    BaseHolder的优化


    1. 使ViewHolder仅仅用来缓存View。

    2. 加入SparseArray,使之来缓存View。

    3. 加入BaseHolder(View view)构造器,外部更方便控制View。

    4. 保留getContext()方法,方便获取Context对象。

    5. 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的封装优化》

  • 相关阅读:
    multimap-swap
    multimap-size
    multimap-rend
    CentOS的利手:“Screen”一个可以在多个进程之间多路复用一个物理终端的窗口管理器
    对TCP/IP网络协议的深入浅出归纳
    程序员的数学:汉诺塔递归与非递归求解
    多柱汉诺塔问题探究
    汉诺塔问题的递归实现(扩展)
    CentOS---网络配置详解
    VMWare虚拟机下CentOS 配置网络实现远程连接,提供Web访问
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/7388139.html
Copyright © 2020-2023  润新知