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

关于Graywater的系列文章

  1. RecyclerView的超强辅助Graywater——理论篇
  2. RecyclerView的超强辅助Graywater——基础实操篇
  3. RecyclerView的超强辅助Graywater——点击事件
  4. 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就是对我的鼓励。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值