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就是对我的鼓励。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,681评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,710评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,623评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,202评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,232评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,368评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,795评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,461评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,647评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,476评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,525评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,226评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,785评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,857评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,090评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,647评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,215评论 2 341

推荐阅读更多精彩内容