美文网首页Android
RecyclerView的超强辅助Graywater——点击事件

RecyclerView的超强辅助Graywater——点击事件

作者: 程序员张晴天 | 来源:发表于2018-11-08 20:33 被阅读94次

    关于Graywater的系列文章

    1. RecyclerView的超强辅助Graywater——理论篇
    2. RecyclerView的超强辅助Graywater——基础实操篇
    3. RecyclerView的超强辅助Graywater——点击事件

    上一篇写了Graywater的基础使用,但是没讲点击事件,这一篇文章就把点击事件给补充上。还是使用的基础实操篇中的GraywaterPrimaryDemo继续写。

    先展示点击效果图:

    Graywater点击事件.gif

    在RecyclerView中如果需要点击事件,我们通常会给RecyclerViewd.Adapter传入一个我们自定义的接口引用,比如OnItemClickListener。然后在onBindViewHolder()方法中将需要点击事件的控件,比如Button,实现View的OnClickListener接口,再使用我们自定义的方法,最后在MainActivity中实现自定义的接口。

            holder.button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (clickListener != null) {
                        clickListener.onClickItem(position);
                    }
                }
            });
    

    Graywater跟前者也是比较相似的,最大的不同的是Graywater自己提供了一个点击事件的接口(GraywaterAdapter.ActionListener)和一个点击事件代理(GraywaterAdapter.ActionListenerDelegate)来管理点击事件。通过在Binder类中传入ViewHolder所持有的接口代理,在ItemBinder中实现接口的act()方法,来完成点击事件的实现。

    实际上,是GraywaterAdapter.ActionListenerDelegate代理实现了View的OnClickListener接口,然后在onClick方法中在调用GraywaterAdapter.ActionListener的act方法。

            @Override
            public void onClick(final View v) {
                actionListener.act(model, holder, v, binders, binderIndex, obj);
            }
    

    接下来就一步步的讲解怎么实现点击事件,点击事件也可以根据上一篇文章中代码的顺序来写。

    1. 给需要点击事件的控件添加id值

    每个Item都由一个RelativeLayout作为最外层的控件,里面放了一个TextView和一个ImageView,给RelativeLayout添加android:id="@+id/item_layout"属性

    2. 在对应ViewHolder类中添加对应的View并创建ActionListenerDelegate的对象

    在EntertainViewHolder里面添加RelativeLayout的控件。

    重点!需要在ViewHolder中创建代理对象,使用holder来统一管理所有的view和点击代理对象。创建ActionListenerDelegate对象时候需要也需要传入对应的model和viewholder的泛型参数,当然这里就是EntertainPrimitive和EntertainViewHolder。

        private GraywaterAdapter.ActionListenerDelegate<EntertainPrimitive, EntertainViewHolder>
                mActionListenerDelegate = new GraywaterAdapter.ActionListenerDelegate<>();
    

    别忘记在最后也要添加对应的get方法。

    3.在Binder类的bind方法中setOnClickListener()

    Graywater官方Demo中,要想实现点击事件,就必须要在bind方法里让点击代理getmActionListenerDelegate执行update()方法。看Graywater源码可以知道update方法实际上就是把相关参数都保存下来,然后在act方法中把相关的引用传过去使用。

    在update方法后,需要点击事件的View就可以在setOnClickListener()中传入点击代理了,最后记得要在unbind()方法中给setOnClickListener()传入null值做清理。

        @Override
        public void bind(@NonNull EntertainPrimitive model, @NonNull EntertainViewHolder holder, @NonNull List<GraywaterAdapter.Binder<? super EntertainPrimitive, ? extends EntertainViewHolder>>
                binders, int binderIndex, @NonNull GraywaterAdapter.ActionListener<EntertainPrimitive, EntertainViewHolder> actionListener) {
            Picasso.get().load(model.getUrls().get(binderIndex)).placeholder(R.mipmap.ic_launcher).into(holder.getImg());
            holder.getTitle().setText(model.getTitles().get(binderIndex));
    
            holder.getmActionListenerDelegate().update(actionListener, model, holder, binders, binderIndex, null);
            holder.getMainLayoutView().setOnClickListener(holder.getmActionListenerDelegate());
        }
    
        @Override
        public void unbind(@NonNull EntertainViewHolder holder) {
            holder.getMainLayoutView().setOnClickListener(null);
        }
    

    update()方法所需要传入的参数基本上就是bind方法中的参数,需要注意的是最后一个Object参数,这个Object参数是用来传递我们想要传递的值的,类似Intent传值的作用一样。一般都用不到,可以直接传null。

    holder.getmActionListenerDelegate().update(actionListener, model, holder, binders, binderIndex, null);
    

    4.ItemBinder类实现GraywaterAdapter.ActionListener接口,并实现act()方法

    EntertainItemBinder需要实现GraywaterAdapter.ActionListener接口,然后就可以在act方法中具体实现我们的点击事件了。

    在GraywaterAdapter.ActionListener接口中需要传入model的泛型参数和viewholder的泛型参数,在EntertainItemBinder中,就传入对应的EntertainPrimitive和EntertainViewHolder。

    看一下act方法的实现,其实就是类似RecyclerView.Adapter中的实现:

        @Override
        public void act(@NonNull EntertainPrimitive model, @NonNull EntertainViewHolder holder, @NonNull View v, @NonNull List<GraywaterAdapter.Binder<? super EntertainPrimitive, ? extends
                EntertainViewHolder>> binders, int binderIndex, @Nullable Object obj) {
            switch (v.getId()) {
                case R.id.item_layout:
                    onItemClickListener.onClickItem(model.getTitles().get(binderIndex));
                    break;
            }
        }
    

    5.写接口传入,MainActivity实现接口

    一般在写点击事件时,我们一般会习惯自定义一个点击事件接口,这里也不例外,我自定义了一个OnItemClickListener接口。让MainActivity实现了这个接口,并将接口传入PrimitiveAdapter中。

    public interface OnItemClickListener {
        void onClickItem(String name);
    }
    

    MainActivity实现了onClickItem方法,就可以使用传过来的name参数做相应的业务处理了。

    看一下OnItemClickListener引用的传递顺序。

    首先是MainActivity

    mPrimitiveAdapter = new PrimitiveAdapter(this);    //因为MainActivity实现了OnItemClickListener接口,所以传入this
    mRecyclerView.setAdapter(mPrimitiveAdapter);
    

    再是PrimitiveAdapter的构造方法,将OnItemClickListener传给EntertainItemBinder。

        public PrimitiveAdapter(OnItemClickListener listener) {
            register(new EntertainViewHolderCreator(), EntertainViewHolder.class);  //将creator和对应的viewholder绑定
    
            EntertainBinder entertainBinder = new EntertainBinder();
            EntertainItemBinder entertainItemBinder = new EntertainItemBinder(entertainBinder, listener);
            register(EntertainPrimitive.class, entertainItemBinder, entertainItemBinder);  //将itemBinder和指定的数据类型绑定
        }
    

    注意构造方法中的第二个register()方法的第三个参数也是entertainItemBinder,从源码可知,要求传入的参数是GraywaterAdapter.ActionListener,也就是在ItemBinder实现该接口后就传入ItemBinder,否则就传入null。

        protected void register(@NonNull final MT modelType,
                                @NonNull final ItemBinder<? extends T, ? extends VH> parts,
                                @Nullable final ActionListener<? extends T, ? extends VH> listener) {
            mItemBinderMap.put(modelType, parts);
            mActionListenerMap.put(modelType, listener);
        }
    

    Graywater有5个基本变量,mItemBinderMap和mActionListenerMap就是其中两个,这两个变量都是Map类型。Graywater中5个基本变量除开mItems不是字典类型,其他4个都是这种字典类型。这是Graywater的核心,以字典的方式,将model映射到viewholder上。register就是在匹配映射关系,将viewholder和viewholdercreator映射起来。将model映射到ItemBinder上,将model映射到Actionlistener上,由此来组成第一篇文章中所展示的映射网状关系,并通过映射关系,来快速查找所需要的类。

    原理图1.png

    到这里,基本上点击事件就讲完了,有什么错误或说的不清楚的地方欢迎大家指正。

    P.S.
    Graywater 官方Demo Github地址
    GraywaterPrimaryDemo Github地址 如果对大家有帮助的话,star就是对我的鼓励。

    如果对你有帮助的话,点赞、评论、赞赏都是对我的鼓励,也是支持我写下去的动力,谢谢!

    相关文章

      网友评论

        本文标题:RecyclerView的超强辅助Graywater——点击事件

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