美文网首页
对RecyclerView.Adapter做一个简单的封装2

对RecyclerView.Adapter做一个简单的封装2

作者: 柠檬果然酸 | 来源:发表于2018-06-18 15:41 被阅读0次

    本篇是对上一篇对RecyclerView.Adapter做一个简单的封装内容的补充 ,如果没有看过上一篇文章,请先阅读上一篇文章。

    在上一篇文章的末尾提到,BaseRecyclerAdapter虽然能够简化部分功能的代码量,但是对于为itemView的每一个控件绑定监听器这一功能是没有做到简化的,本篇的内容就是解决这个问题。

    先贴出没有封装的适配器代码

    public class RecordAdapter extends RecyclerView.Adapter<RecordAdapter.RecordHolder> {
    
        private OnItemClickListener onItemClickListener;
    
        //上下文环境
        private Context context;
        //数据集合
        private List<Record> data;
    
        public RecordAdapter(Context context, List<Record> data) {
            this.context = context;
            this.data = data;
        }
    
        /**
         * 刷新数据
         * @param data
         */
        public void refresh(List<Record> data){
            this.data = data;
            notifyDataSetChanged();
        }
    
        @Override
        public RecordHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(context).inflate(R.layout.item_record, parent, false);
            return new RecordHolder(view);
        }
    
        @Override
        public void onBindViewHolder(RecordHolder holder, int position) {
            Record record = data.get(position);
            holder.bind(record);
        }
    
    
        @Override
        public int getItemCount() {
            return data == null ? 0 : data.size();
        }
    
        public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
            this.onItemClickListener = onItemClickListener;
        }
    
        class RecordHolder extends RecyclerView.ViewHolder {
    
            //数据
            private Record record;
    
            TextView tvId;
            TextView tvRemark;
            TextView tvCreatedAt;
    
            public RecordHolder(View itemView) {
                super(itemView);
                tvId = (TextView) itemView.findViewById(R.id.tvId);
                tvRemark = (TextView) itemView.findViewById(R.id.tvRemark);
                tvCreatedAt = (TextView) itemView.findViewById(R.id.tvCreatedAt);
                bindListener();
            }
    
            //绑定数据
            public void bind(Record record) {
                this.record = record;
                tvId.setText(record.getId().toString());
                tvRemark.setText(record.getRemark());
                tvCreatedAt.setText(record.getCreatedAt().toString());
            }
    
            /**
             * 绑定监听器
             */
            private void bindListener() {
                tvId.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (onItemClickListener != null) {
                            onItemClickListener.onIdClick(v, record);
                        }
                    }
                });
    
                tvRemark.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (onItemClickListener != null) {
                            onItemClickListener.onRemarkClick(v, record);
                        }
                    }
                });
    
                tvCreatedAt.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (onItemClickListener != null) {
                            onItemClickListener.onCreationTimeClick(v, record);
                        }
                    }
                });
            }
        }
    
    
        public interface OnItemClickListener {
    
            /**
             * 当id被点击
             * @param v
             * @param record
             */
            void onIdClick(View v, Record record);
    
            /**
             * 当备注被点击
             * @param v
             * @param record
             */
            void onRemarkClick(View v, Record record);
    
            /**
             * 当创建时间被点击
             * @param v
             * @param record
             */
            void onCreationTimeClick(View v, Record record);
        }
    }
    

    运行

    MainActivity.java
    public class MainActivity extends AppCompatActivity {
    
        private RecyclerView recyclerView;
        private RecordAdapter adapter;
        private List<Record> records;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
            recyclerView.setLayoutManager(new LinearLayoutManager(this));
    
            //模拟数据
            records = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                Record record = new Record();
                record.setId(i);
                record.setRemark("第" + i + "条备注");
                record.setCreatedAt(new Date());
                records.add(record);
            }
            adapter = new RecordAdapter(this, records);
            //绑定监听器
            adapter.setOnItemClickListener(new RecordAdapter.OnItemClickListener() {
                @Override
                public void onIdClick(View v, Record record) {
                    Toast.makeText(MainActivity.this, record.getId().toString(), Toast.LENGTH_SHORT).show();
                }
    
                @Override
                public void onRemarkClick(View v, Record record) {
                    Toast.makeText(MainActivity.this, record.getRemark(), Toast.LENGTH_SHORT).show();
                }
    
                @Override
                public void onCreationTimeClick(View v, Record record) {
                    Toast.makeText(MainActivity.this, record.getCreatedAt().toString(), Toast.LENGTH_SHORT).show();
                }
            });
    
            recyclerView.setAdapter(adapter);
        }
    }
    
    运行效果如下
    运行结果

    每个控件的点击效果可以自己亲自测试,接下来同样通过对比的方式讲解封装思路。

    RecordAdapter中的回调接口OnItemClickListener
        public interface OnItemClickListener {
    
            /**
             * 当id被点击
             * @param v
             * @param record
             */
            void onIdClick(View v, Record record);
    
            /**
             * 当备注被点击
             * @param v
             * @param record
             */
            void onRemarkClick(View v, Record record);
    
            /**
             * 当创建时间被点击
             * @param v
             * @param record
             */
            void onCreationTimeClick(View v, Record record);
        }
    
    RecordHolder中的控件
            TextView tvId;
            TextView tvRemark;
            TextView tvCreatedAt;
    

    可以看到OnItemClickListener中的抽象方法是和RecordHolder中的控件是一一对应的,而在封装的BaseViewHolder中控件是这样的

            // itemView 中的控件缓存在这里
            private SparseArray<View> views;
    

    那么BaseRecyclerAdapter中的回调接口应该怎么写?
    不知道大家用没用过PopupMenuPopupMenu绑定点击事件如下

    popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            switch (item.getItemId()) {
                case R.id.view1:
                    ...
                    break;
    
                case R.id.view2:
                    ...
                    break;
    
                case R.id.view3:
                    ...
                    break;
            }
    
            return false;
        }
    });
    

    从这里可以获得灵感,为BaseViewHolder中所有的控件都绑定监听器,然后根据控件id的不同来做不同的操作。

    BaseRecyclerAdapter中的OnItemClickListener
        /**
         * 回调接口
         * @param <T>
         */
        public interface OnItemClickListener<T> {
    
            void onItemClick(View view, T t);
        }
    
    BaseViewHolder
    class BaseViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    
            // itemView 中的控件缓存在这里
            private SparseArray<View> views;
            //数据
            private T t;
    
            public BaseViewHolder(View itemView) {
                super(itemView);
                views = new SparseArray<>();
            }
    
            public void setT(T t) {
                this.t = t;
            }
    
            /**
             * 获取 itemView 中的控件
             *
             * @param id
             * @return
             */
            public View getView(int id) {
                View view = views.get(id);
                if (view == null) {
                    view = itemView.findViewById(id);
                    views.put(id, view);
                    view.setOnClickListener(this);
                }
                return view;
            }
    
            @Override
            public void onClick(View v) {
                if (onItemClickListener != null) {
                    onItemClickListener.onItemClick(v, t);
                }
            }
        }
    

    与之前的BaseViewHolder相比多了几处东西:
    1.private T t这个属性以及它的set方法
    2.getView(int id)方法中多了一行代码view.setOnClickListener(this);
    3.onClick方法
    这3处代码所做的只有一件事情,就是为private SparseArray<View> views中的所有控件绑定监听器。

    BaseRecyclerAdapter也有几处地方需要修改

    1.添加成员变量以及它的set方法

        private OnItemClickListener<T> onItemClickListener;
    
        public void setOnItemClickListener(OnItemClickListener<T> onItemClickListener) {
            this.onItemClickListener = onItemClickListener;
        }
    

    2.修改onBindViewHolder

        @Override
        public void onBindViewHolder(BaseRecyclerAdapter.BaseViewHolder holder, int position) {
            T t = data.get(position);
            holder.setT(t);
            bindData(holder, t);
        }
    

    大功告成

    完整代码

    public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseRecyclerAdapter.BaseViewHolder> {
    
        private OnItemClickListener<T> onItemClickListener;
    
        //上下文环境
        private Context context;
        //数据集合
        private List<T> data;
    
        /**
         * 刷新数据
         *
         * @param data
         */
        public void refresh(List<T> data) {
            this.data = data;
            notifyDataSetChanged();
        }
    
        /**
         * 添加数据
         *
         * @param data
         */
        public void append(List<T> data) {
            this.data.addAll(data);
            notifyDataSetChanged();
        }
    
        public BaseRecyclerAdapter(Context context, List<T> data) {
            this.context = context;
            this.data = data;
        }
    
        @Override
        public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(context).inflate(getItemLayoutId(), parent, false);
            return new BaseViewHolder(view);
        }
    
        @Override
        public void onBindViewHolder(BaseRecyclerAdapter.BaseViewHolder holder, int position) {
            T t = data.get(position);
            holder.setT(t);
            bindData(holder, t);
        }
    
        @Override
        public int getItemCount() {
            return data == null ? 0 : data.size();
        }
    
        public void setOnItemClickListener(OnItemClickListener<T> onItemClickListener) {
            this.onItemClickListener = onItemClickListener;
        }
    
        /**
         * 将数据绑定到itemView视图上
         *
         * @param holder
         * @param t
         */
        public abstract void bindData(BaseViewHolder holder, T t);
    
        /**
         * 子类通过重写此方法设置itemView项的布局视图
         *
         * @return
         */
        public abstract int getItemLayoutId();
    
        /**
         * 封装 ViewHolder
         */
        class BaseViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    
            // itemView 中的控件缓存在这里
            private SparseArray<View> views;
            //数据
            private T t;
    
            public BaseViewHolder(View itemView) {
                super(itemView);
                views = new SparseArray<>();
            }
    
            public void setT(T t) {
                this.t = t;
            }
    
            /**
             * 获取 itemView 中的控件
             *
             * @param id
             * @return
             */
            public View getView(int id) {
                View view = views.get(id);
                if (view == null) {
                    view = itemView.findViewById(id);
                    views.put(id, view);
                    view.setOnClickListener(this);
                }
                return view;
            }
    
            @Override
            public void onClick(View v) {
                if (onItemClickListener != null) {
                    onItemClickListener.onItemClick(v, t);
                }
            }
        }
    
        /**
         * 回调接口
         * @param <T>
         */
        public interface OnItemClickListener<T> {
    
            void onItemClick(View view, T t);
        }
    }
    

    使用

    MainActivity中的

            //绑定监听器
            adapter.setOnItemClickListener(new RecordAdapter.OnItemClickListener() {
                @Override
                public void onIdClick(View v, Record record) {
                    Toast.makeText(MainActivity.this, record.getId().toString(), Toast.LENGTH_SHORT).show();
                }
    
                @Override
                public void onRemarkClick(View v, Record record) {
                    Toast.makeText(MainActivity.this, record.getRemark(), Toast.LENGTH_SHORT).show();
                }
    
                @Override
                public void onCreationTimeClick(View v, Record record) {
                    Toast.makeText(MainActivity.this, record.getCreatedAt().toString(), Toast.LENGTH_SHORT).show();
                }
            });
    

    替换成

            //绑定监听器
            adapter.setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener<Record>() {
                @Override
                public void onItemClick(View view, Record record) {
                    switch (view.getId()) {
                        case R.id.tvId:
                            Toast.makeText(MainActivity.this, record.getId().toString(), Toast.LENGTH_SHORT).show();
                            break;
    
                        case R.id.tvRemark:
                            Toast.makeText(MainActivity.this, record.getRemark(), Toast.LENGTH_SHORT).show();
                            break;
    
                        case R.id.tvCreatedAt:
                            Toast.makeText(MainActivity.this, record.getCreatedAt().toString(), Toast.LENGTH_SHORT).show();
                            break;
                    }
                }
            });
    

    运行效果自己亲自试一试就知道了。

    相关文章

      网友评论

          本文标题:对RecyclerView.Adapter做一个简单的封装2

          本文链接:https://www.haomeiwen.com/subject/whtneftx.html