基于BaseRecyclerViewAdapterHelper封装的多条目Adapter,方便快捷,便于维护

  项目地址: https://github.com/chaychan/MultipleItemRvAdapter

  已提交并整合到BaseRecyclerViewAdapterHelper,下面介绍如何使用改进后的多条目adapter。

  效果图,我之前做过的精仿今日头条,新闻列表中有好几种布局:

home.jpg

Apk下载地址

[点击下载体验]

  MultipleItemRvAdapter是在BaseRecyclerViewAdapterHelper的基础上对BaseQuickAdapter进行封装,在包含BaseRecyclerViewAdapterHelper所有功能的基础上,对其中的多条目布局处理逻辑进行了封装,将adapter中每种子条目单独出对应的ItemProvider,这样方便相应条目做相关的业务逻辑。

项目介绍

BaseRecyclerViewAdapterHelper

image

  BaseRecyclerViewAdapterHelper是一个封装好的万能RecyclerView的适配器,可以方便快捷地完成adapter的编写,包含一种或多种子条目的处理且拥有许多强大的功能,比如上拉加载更多、支持添加动画、可以添加子条目的点击、长按事件、添加头部和底部等,现拥有12.6K多的star数,受到不少Android开发者的青睐,我在项目的开发中也使用BaseRecyclerViewAdapterHelper,是一名忠实的粉丝。

BaseRecyclerViewAdapterHelper 多条目布局的不足之处

  BaseRecyclerViewAdapterHelper中对多条目布局的逻辑都放在convert()方法中,通过判断对应的itemViewTyper来进行相应子条目的处理,当条目特别多以及拥有复杂业务逻辑的情况,convert()中的处理将会特别多,不便于往后项目的维护,比如IM里面的消息列表,有文本、图片、语音、位置、红包、转账等,有很多种不同布局,对应的逻辑也比较多,在只使用BaseRecyclerViewAdapterHelper的情况下,对应消息列表的adapter代码就已经破一千行,全部条目的逻辑都在一个adapter种,觉得不是特别合理,如下是消息列表的adapter:

public class MessageListAdapter extends BaseQuickAdapter<Message,BaseViewHolder>{

public static final int TYPE_TEXT = 0;
public static final int TYPE_IMG = 1;

public MessageListAdapter(int layoutResId, @Nullable List<Message> data) {
        super(layoutResId, data);

        setMultiTypeDelegate(new MultiTypeDelegate<Message>() {
            @Override
            protected int getItemType(Message message) {
                if (message instanceof TextMessage){
                    return TYPE_TEXT;
                }else if (message instanceof ImageMessage){
                    return TYPE_IMG;
                }
                // else if(){
                //     //还有其他消息类型,比如语音、位置、红包、转账等
                // }

                return 0;
            }
        });

        getMultiTypeDelegate()
                .registerItemType(TYPE_TEXT, R.layout.item_text_message)
                .registerItemType(TYPE_IMG, R.layout.item_image_message);
                //还有其他消息类型,比如语音、位置、红包、转账等
    }

    @Override
    protected void convert(BaseViewHolder helper, Message item) {
        int viewType = helper.getItemViewType();
        switch (viewType){
            case TYPE_TEXT:
                //文本消息的业务逻辑

                break;
            case TYPE_IMG:
                //图片消息的业务逻辑

                break;
             // case 语音、位置、红包、转账等
            // break;
        }
    }
}

  当子条目有许多种的时候,convert()中的逻辑将会很多,不便于项目的维护,故而封装了MultipleItemRvAdapter,将每个条目的逻辑处理都交给创建的ItemProvider来处理,这样可以在对应条目的ItemProvider写相应的逻辑,方便维护。

如何使用MultipleItemRvAdapter

一、创建对应条目的ItemProvider,继承BaseItemProvider,注解ItemProviderTag中填写对应的viewType的值(建议在对应的adapter中定义常量,每种条目的viewType必须唯一), layout指定对应条目的布局id。

比如文本消息条目的provider:

/**
 * @author ChayChan
 * @description 文本消息条目的provider
 * @date 2018/3/21  14:43
 */
@ItemProviderTag(
    viewType = MessageListAdapter.TYPE_TEXT,
    layout = R.layout.item_text_message
)
public class TextMessageItemProvider extends BaseItemProvider<TextMessage> {

    @Override
    public void convert(BaseViewHolder helper, TextMessage data, int position) {
        //处理相关业务逻辑
        helper.setText(R.id.tv_text, data.text);
    }

    @Override
    public void onClick(BaseViewHolder helper, TextMessage data, int position) {
        //单击事件
        Toast.makeText(mContext, "Click: " + data.text, Toast.LENGTH_SHORT).show();
    }

    @Override
    public boolean onLongClick(BaseViewHolder helper, TextMessage data, int position) {
        //长按事件
        Toast.makeText(mContext, "longClick: " + data.text, Toast.LENGTH_SHORT).show();
        return true;
    }
}

图片消息条目的provider:

/**
 * @author ChayChan
 * @description 图片消息条目的provider
 * @date 2018/3/21  14:43
 */
@ItemProviderTag(
        viewType = MessageListAdapter.TYPE_IMG,
        layout = R.layout.item_image_message
)
public class ImageMessageItemProvider extends BaseItemProvider<ImageMessage> {

    @Override
    public void convert(BaseViewHolder helper, ImageMessage data, int position) {
        //处理相关业务逻辑
        ImageView iv = helper.getView(R.id.iv_img);
        Glide.with(mContext).load(data.imgUrl).into(iv);
    }

    @Override
    public void onClick(BaseViewHolder helper, ImageMessage data, int position) {
        //单击事件
        Toast.makeText(mContext, "Click: " + data.imgUrl, Toast.LENGTH_SHORT).show();
    }

    @Override
    public boolean onLongClick(BaseViewHolder helper, ImageMessage data, int position) {
        //长按事件
        Toast.makeText(mContext, "longClick: " + data.imgUrl, Toast.LENGTH_SHORT).show();
        return true;
    }
}

ItemProvider的convert()方法中用于处理相应的业务逻辑,onClick()中用于处理条目的单击事件,onLongClick()中用于处于条目的长按事件;尽管单击和长按事件adapter中可以通过ssetOnItemClick()和setOnItemLongClick()来处理,但是这里还是有将这两个事件交于itemProvider,开发者可以根据具体需要选择使用其中一种方式。

二、创建对应的adapter,继承MultiItemRvAdapter,如MessageListAdapter:

/**
 * @author ChayChan
 * @description: 消息列表的adapter
 * @date 2018/3/21  14:40
 */

public class MessageListAdapter extends MultipleItemRvAdapter<Message> {

    public static final int TYPE_TEXT = 0;
    public static final int TYPE_IMG = 1;

    public MessageListAdapter(@Nullable List<Message> data) {
        super(data);

        //构造函数若有传参可以在调用finishInitialize()之前进行赋值,赋值给全局变量
        //这样getViewType()和registerItemProvider()方法中可以获取到传过来的值
        //getViewType()中可能因为某些业务逻辑,需要将某个值传递过来进行判断,返回对应的viewType
        //registerItemProvider()中可以将值传递给ItemProvider
        
        finishInitialize();//调用该方法告知MultipleItemRvAdapter1️已初始化完构造函数参数的传递
    }

    @Override
    protected int getViewType(Message message) {
        //返回对应的viewType
        if (message instanceof TextMessage) {
            return TYPE_TEXT;
        } else if (message instanceof ImageMessage) {
            return TYPE_IMG;
        }
        return 0;
    }


    @Override
    public void registerItemProvider() {
        //注册相关的条目provider
        mProviderDelegate.registerProvider(new TextMessageItemProvider()); //注册文本消息条目的itemProvider
        mProviderDelegate.registerProvider(new ImageMessageItemProvider());//注册图片消息条目的itemProvider
    }

}

  adapter中需要实现getViewType()和registerItemProvider()两个方法。getViewType()通过判断相关逻辑返回不同的viewType,registerItemProvider()用于注册自己所定义的所有子条目的ItemProvider。

三、为RecyclerView设置相应的adapter:

    mRvMessages = findViewById(R.id.rv_message);

    mRvMessages.setHasFixedSize(true);
    mRvMessages.setLayoutManager(new LinearLayoutManager(this));

    String imgUrl1 = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1521627479112&di=7b109af49f8c1c193c3173306cf58680&imgtype=0&src=http%3A%2F%2Fimg.xgo-img.com.cn%2Fpics%2F1538%2F1537620.jpg";
    String imgUrl2 = "https://timgsa.baidu.com/timg?image&quality=80&size=b10000_10000&sec=1521617426&di=d6537bb0ef71984e4a1d14e4b18ba169&src=http://img1d.xgo-img.com.cn/pics/789/788784.jpg";

    mMessages.add(new TextMessage("你好呀,哈哈哈哈,呜啦啦啦啦"));
    mMessages.add(new ImageMessage(imgUrl1));
    mMessages.add(new TextMessage("嗯嗯,今天天气真不错!"));
    mMessages.add(new ImageMessage(imgUrl2));

    mRvMessages.setAdapter(new MessageListAdapter(mMessages));

效果图:

image

  由于该库中包含BaseRecyclerViewAdapterHelper库,所以BaseRecyclerViewAdapterHelper拥有的它也具有。

导入方式

在项目根目录下的build.gradle中的allprojects{}中,添加jitpack仓库地址,如下:

allprojects {
    repositories {
        jcenter()
        maven { url 'https://jitpack.io' }//添加jitpack仓库地址
    }
}

打开app的module中的build.gradle,在dependencies{}中,添加依赖,如下:

dependencies {
        compile 'com.github.chaychan:MultipleItemRvAdapter:1.0.2' //建议使用最新版本
}

最新发布的版本可以查看

https://github.com/chaychan/MultipleItemRvAdapter/releases

支持和鼓励

  如果觉得对你有帮助,请帮忙star一下,让更多人可以看到,谢谢!这样我会更加有动力去完善好这个项目;

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

推荐阅读更多精彩内容