BRVAH的BaseRecyclerViewAdapterHelper与MVVM模式优雅结合,Recyclerview如何在Databinding中快捷、方便地使用(一)

BRVAH的BaseRecyclerViewAdapterHelper与MVVM模式优雅结合(其二)
BRVAH的BaseRecyclerViewAdapterHelper与MVVM模式优雅结合(其三)
(我原先的图片找不到了,而我的文章又是从我的博客上粘贴来的,如果影响的可以去我博客看)
先一句话描述这个控件的功能:将BaseRecyclerViewAdapterHelper与MVVM模式完美结合起来,实现更加方便,快捷的列表加载,帮您省去大量的时间写各种复杂的适配器,使项目的代码结构更加简洁优雅。

曾今有句Android界的谶言:Android UI开发只要会用列表就顶半边天。我们日常开发中,用到的列表是何其多,大量的列表,就意味着大量的适配器,更意味着更大量的bean类、item布局和复杂繁多的逻辑,所以,有一套方便,快捷的列表模板是何其重要。现在都已经9020年了,相信大家已经从MVC模式,过渡MVP模式,到MVVM模式了吧,如果还没用MVVM模式的,你就out了!(这段是废话,可以省略不看)

因为我公司项目是MVVM模式的,然后以前一个老Android同事写过一个控件,就是能很方便地将列表跟viewModel绑定在一起,使得代码精简很多。不过也有一些不足,例如不支持多布局的绑定,然后我这边就站在巨人的肩膀上,将控件完善一下。

使用本控件的前提,项目使用MVVM开发模式,列表适配器是使用BRVAH的BaseRecyclerViewAdapterHelper万能适配器(本控件支持非使用AndroidX和使用AndroidX的条件,贼贴心)。

1.地址

2.首页调用展示

3.如何依赖

4.调用BRVAH自带的动画,及line模式

5.自定义动画调用设置,及grid模式

6.多布局实现,item实现MultipleItem。

7.多布局实现,item不实现MultipleItem的调用方式

8.如何用databinding模式添加多个头部和脚部,并且有各自事件

9.空布局及下拉刷新

10.侧滑删除

11.长按拖动

12.侧滑删除和长按拖动相结合

13.ExpandableItem,可扩展的多布局使用

14.下拉刷新,上拉加载

15.仿聊天界面,从下到上加载数据

16.双列表使用,仿外卖(甚至可以更多列表)

17.支持使用自己的适配器来调用

18.支持列表侧滑

地址

废话不多说,先上Github的demo。从demo中,就可以看到项目结构精简

如果你项目中,是不使用AndroidX的,请食用该地址:https://github.com/CaesarShao/CSBrvahBinding

如果项目中使用了AndroidX的,请食用该地址:https://github.com/CaesarShao/CSBrvahBindingX

(本篇文章内容有点多,要文章跟demo一起看才相得益彰。希望大家能耐心看完,之后,你会觉得该控件真心赞,帮你项目开发更加精简)

默认习惯,先上图再说,效果图很简单,主要是里面的代码逻辑:

20191224144046284.gif
20191224144143699.gif
20191224144222624.gif

2019122413403079.jpg
2019122413405276.jpg
20191224152115326.jpg
20191224152141308.jpg

首先,大家可以看我library中的CSBrvahBindingAdapter这个类,里面就是通过BindingAdapter的方法,将列表跟适配器绑定在一起。然后是CSItemBindingAdapter这个适配器,这就是本控件核心的适配器了,在这个adapter中,调用了databinding的绑定方法。然后大家可以看BaseBindingViewModel这个类,这个是viewModel的基类,里面将一些属性和方法定义,还有仿网络请求的动作跟列表结合。后面边写边解释。

还有再提醒一下,大家看文章,要跟demo结合起来食用,不然可能会看得有点模糊。

首页样式

例子列表截图:


20191224120242428.png

首页列表调用方式:

非常简单,这个是Activity的内容,只要绑定viewModel,然后调用model.load(),加载列表的数据就可以了

class MainActivity : AppCompatActivity() {
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
        val model = MainViewModel()
        binding.vm = model
        model.load()
        CSLog.Open()//测试用开启日志
    }
}

首页的viewModel:

public class MainViewModel extends BaseBindingViewModel<MainData> {
 
    @Override//获取绑定的布局和数据
    protected Map<Integer, CSBravhItemBinding> getItemBinding() {
        Map<Integer, CSBravhItemBinding> mp = new HashMap<>();
        mp.put(0, new CSBravhItemBinding(BR.bean, R.layout.item_main, BR.action, new Action()));
        return mp;
    }
 
    @Override//已经集成好的加载数据的方法
    public void load() {
        load(getData());
    }
 
    //另外的点击事件动作,我为了方便这样写,也可以mvvm模式默认是写在data数据中
    public class Action implements CSAction1<MainData> {
        @Override
        public void call(MainData param) {
            Intent intent = new Intent(FramGroble.INSTANCE.getTopActivity(), param.activity);
            FramGroble.INSTANCE.getTopActivity().startActivity(intent);
        }
    }
 
    //模拟网络请求的数据
    private Flowable<List<MainData>> getData() {
        return Flowable.create(new FlowableOnSubscribe<List<MainData>>() {
            @Override
            public void subscribe(FlowableEmitter<List<MainData>> emitter) throws Exception {
                ArrayList<MainData> data = new ArrayList<>();
                data.add(new MainData("Animation,line,加载动画效果", AnimationActivity.class));
                data.add(new MainData("Animation,Grid,加载自定义动画效果", AnimationCustomActivity.class));
                data.add(new MainData("MultipleItem,line,多布局", MultipleLineActivity.class));
                data.add(new MainData("非MultipleItem,Grid,多布局,(不想继承MultiItemEntity,用自己的bean类)", NonMultipleActivity.class));
                data.add(new MainData("添加多个头部和尾部,有各自的数据,优雅", HeadFootActivity.class));
                data.add(new MainData("空布局及下拉刷新", EmptyRefreshActivity.class));
                data.add(new MainData("侧滑删除", SwipeActivity.class));
                data.add(new MainData("长按拖动,多布局", DragActivity.class));
                data.add(new MainData("可扩展的,多布局", ExpandActivity.class));
                data.add(new MainData("下拉刷新,上拉加载", LoadMoreLineActivity.class));
                data.add(new MainData("聊天界面,下拉加载", LoadMoreChatActivity.class));
                data.add(new MainData("2个列表的绑定,仿外卖", TwoListActivity.class));
                data.add(new MainData("用自己的适配器(继承万能适配器)", CustomAdapterActivity.class));
                emitter.onNext(data);
                emitter.onComplete();
            }
        }, BackpressureStrategy.BUFFER);
    }
 
    @Override//设置自定义item的间距
    public RecyclerView.ItemDecoration onitemDecoration() {
        return new NormalLineDecoration(30, true);
    }
}

viewModel中,没有复杂的逻辑调用,只有一些回调。只要继承BaseBindingViewModel<>,里面设置数据的泛型,(多布局泛型下面说明),通过getItemBinding()这个回调,设置每个item的布局与绑定的数据(可以绑定多个data),其中map的键就是itemType的类型,如果是单布局,写0就可以了,如果是多布局,按照itemType类型写,mainActivity中的item,还另外绑定了一个事件Action,我这边是设置为item的点击事件。load()中的回调,调用了load(getData())来加载数据(我这边使用rxjava来模拟数据的加载,现在的项目基本都是用retrofit和rxjava结合获取网络请求)。最下面的onitemDecoration()回调,是设置recyclerview的item间距。是不是很干净整洁,逻辑一目了然。

这时,就会有人问:哎呀,古诚欺啊,为什么没有看到列表的适配器啊。嘿嘿,适配器已经封装在BaseBindingViewModel中了,别急,后面会一一讲到,接下来,来看布局文件,超级简单:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
 
    <data>
        <variable
            name="vm"
            type="com.caesar.brvahbinding.MainViewModel" />
    </data>
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
 
        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:cs_brvah_Decoration="@{vm.itemDecoration}"
            app:cs_brvah_adapter="@{vm.bindingAdapter}"
             />
    </LinearLayout>
</layout>

databinging的格式就不多说了,其中,app:cs_brvah_adapter="@{vm.bindingAdapter}",就是绑定viewModel中的适配器,因为在BaseBindingViewModel这个基类中已经初始化好了,所以直接引用就可以了。app:cs_brvah_Decoration="@{vm.itemDecoration}"这个是绑定Decoration,也就是设置每个item的间隔,在上面的viewModel中,不是有onitemDecoration()回调么,就可以自己定制。

怎么样,是不是特别地简便。目前只是简单地说明一个,接下来会慢慢地讲解,越后面,本控件的便捷之处就越会体现,有不懂的可以集合例子看,就会明白的。

怎么引用该控件

这时就会有人问:哎呀,古诚欺啊,那该怎么依赖这么方便快捷的控件呢?

很简单,在根build.gradle中:

allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

然后,如果你项目是使用AndroidX的,就引用该地址:

dependencies {
            implementation 'com.github.CaesarShao:CSBrvahBindingX:1.0.8'
    }

如果项目不支持AndroidX的,就引用:

    dependencies {
            implementation 'com.github.CaesarShao:CSBrvahBinding:1.0.8'
    }

还有,因为我依赖的万能适配器的版本是com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.50,所以大家项目中的版本最好不低于2.9.50。不然可能会有兼容问题。

是不是贼贴心,都给大家考虑到了.好接下来我就一一讲解具体的调用方式,请大家耐心看下去。

调用BRVAH自带的动画及line模式

20191224134731808.png

Activity的调用我就不讲了,很简单,大家看AnimationActivity这个类常规调用,先将代码贴出来:

public class AnimationViewModel extends BaseBindingViewModel<SimpleData> {
 
    public AdapterView.OnItemSelectedListener onItemClickListener = getOnItemCli();
 
    //构造方法,里面可以设置基础属性
    public AnimationViewModel() {
        super();
        //该viewmodel是演示效果,实际在构造方法中,直接调用即可,
        // animationType.set(BaseQuickAdapter.SLIDEIN_BOTTOM);
    }
 
    @Override
    protected Map<Integer, CSBravhItemBinding> getItemBinding() {
        Map<Integer, CSBravhItemBinding> mp = new HashMap<>();
        mp.put(0, new CSBravhItemBinding(com.caesar.brvahbinding.BR.bean, R.layout.item_simple));
        return mp;
    }
 
    @Override
    public void load() {
        load(CreateData.getSimpleData());
    }
 
    //这个是Spinner控件的OnItemSelectedListener的监听,在布局中绑定,当spinner使用时,会回调这个方法.
    public AdapterView.OnItemSelectedListener getOnItemCli() {
        return new AdapterView.OnItemSelectedListener() {
 
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                switch (position) {
                    case 0:
                        animationType.set(BaseQuickAdapter.SLIDEIN_BOTTOM);
                        break;
                    case 1:
                        animationType.set(BaseQuickAdapter.ALPHAIN);
                        break;
                    case 2:
                        animationType.set(BaseQuickAdapter.SCALEIN);
                        break;
                    case 3:
                        animationType.set(BaseQuickAdapter.SLIDEIN_LEFT);
                        break;
                    case 4:
                        animationType.set(BaseQuickAdapter.SLIDEIN_RIGHT);
                        break;
                }
            }
 
            @Override
            public void onNothingSelected(AdapterView<?> parent) {
 
            }
        };
    }
 
    @Override
    public RecyclerView.ItemDecoration onitemDecoration() {
        return new NormalLineDecoration(30, true);
    }
}
20191224145512617.jpg

大家先看布局文件,有一个app:cs_brvah_animation="@{vm.animationType}",这个就是设置brvah自带的动画效果,当依赖好之后,只要在viewmodel的构造方法中设置,比如animationType.set(BaseQuickAdapter.SLIDEIN_BOTTOM);这样调用就可以了,如果布局中依赖过,它默认的动画效果是BaseQuickAdapter.SLIDEIN_BOTTOM。

然后在RecyclerView中,绑定adapter之后,就是app:cs_brvah_adapter="@{vm.bindingAdapter}",会默认设置RecyclerView的显示方式为LinearLayoutManager。

如何加载自定义动画和GridLayoutManager呢

大家看AnimationCustomActivity这个界面,

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
 
    <data>
 
        <variable
            name="vm"
            type="com.caesar.brvahbinding.animation.AnimationCustomViewModel" />
 
        <import type="com.caesarlib.brvahbinding.CSBrvahLayoutManager" />
    </data>
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{vm.onBack}"
            android:text="返回" />
 
 
        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:cs_brvah_Decoration="@{vm.itemDecoration}"
            app:cs_brvah_adapter="@{vm.bindingAdapter}"
            app:cs_brvah_animation_custom="@{vm.customAnimation}"
            app:cs_brvah_layoutManager="@{CSBrvahLayoutManager.grid(2)}" />
    </LinearLayout>
</layout>
public class AnimationCustomViewModel extends BaseBindingViewModel<SimpleData> {
    
    @Override
    protected Map<Integer, CSBravhItemBinding> getItemBinding() {
        Map<Integer, CSBravhItemBinding> mp = new HashMap<>();
        mp.put(0, new CSBravhItemBinding(com.caesar.brvahbinding.BR.bean, R.layout.item_simple));
        return mp;
    }
 
    @Override
    public void load() {
        load(CreateData.getSimpleData());
    }
    
    @Override
    public RecyclerView.ItemDecoration onitemDecoration() {
        return new GridSpacingItemDecoration(2, 30, true);
    }
 
    @Override//设置自定义动画
    public BaseAnimation onCustomAnimation() {
        return new CustomAnimation();
    }
}

可以看到,布局文件中,绑定了2个其他的东西,其中app:cs_brvah_animation_custom="@{vm.customAnimation}"就是绑定自定义动画,在viewModel中的onCustomAnimation()回调中设置,我这边copy了brvah官方的自定义动画。在布局文件中,还可以看到,我引入了<import type="com.caesarlib.brvahbinding.CSBrvahLayoutManager"/>,在RecyclerView中,我调用,app:cs_brvah_layoutManager="@{CSBrvahLayoutManager.grid(2)}",这个就是将列表的显示方式,设置为2格的GridLayoutManager,大家可以去看看CSBrvahLayoutManager这个类,里面有设置各种LayoutManager的方法。

多布局,实现MultipleItem

大家看MultipleLineActivity这个类,activity还是一如既往的简单,

public class MultiLineViewModel extends BaseBindingViewModel<MultiItemEntity> {
    @Override//多布局根据data的itemtype返回的值,将绑定类型的写上去
    protected Map<Integer, CSBravhItemBinding> getItemBinding() {
        Map<Integer, CSBravhItemBinding> mp = new HashMap<>();
        mp.put(0, new CSBravhItemBinding(com.caesar.brvahbinding.BR.data, R.layout.item_multi_zero));
        mp.put(1, new CSBravhItemBinding(com.caesar.brvahbinding.BR.data, R.layout.item_multi_one));
        mp.put(2, new CSBravhItemBinding(com.caesar.brvahbinding.BR.data, R.layout.item_multi_two));
        return mp;
    }
 
    @Override
    public void load() {
        load(getData());
    }
 
    private Flowable<List<MultiItemEntity>> getData() {
        return Flowable.create(new FlowableOnSubscribe<List<MultiItemEntity>>() {
            @Override
            public void subscribe(FlowableEmitter<List<MultiItemEntity>> emitter) throws Exception {
                ArrayList<MultiItemEntity> data = new ArrayList<>();
                data.add(new MultiDataOne("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new MultiDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img0));
                data.add(new MultiDataTwo("这货是个标题", "这货是个内容加描述", R.mipmap.head_img2));
                data.add(new MultiDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new MultiDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new MultiDataOne("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new MultiDataTwo("这货是个标题", "这货是个内容加描述", R.mipmap.head_img2));
                data.add(new MultiDataOne("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new MultiDataOne("这货是个标题", "这货是个内容加描述", R.mipmap.head_img0));
                data.add(new MultiDataTwo("这货是个标题", "这货是个内容加描述", R.mipmap.head_img0));
                data.add(new MultiDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new MultiDataOne("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                emitter.onNext(data);
                emitter.onComplete();
            }
        }, BackpressureStrategy.BUFFER);
    }
    
    @Override
    public RecyclerView.ItemDecoration onitemDecoration() {
        return new NormalLineDecoration(30, true);
    }
 
}
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
 
    <data>
 
        <variable
            name="vm"
            type="com.caesar.brvahbinding.multiple.MultiLineViewModel" />
 
    </data>
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{vm.onBack}"
            android:text="返回" />
        
        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:cs_brvah_Decoration="@{vm.itemDecoration}"
            app:cs_brvah_adapter="@{vm.bindingAdapter}"
            app:cs_brvah_animation="@{vm.animationType}" />
    </LinearLayout>
</layout>

大家可以看到,布局文件很简单,跟首页的基本一模一样,在MultiLineViewModel中,继承baseviewmodel时,要传泛型为MultiItemEntity,可以看到,是不是跟其他的基本一毛一样,然后每个item的data也都很简单。

这时,就会有同学问了:诶呀,古诚欺啊,如果我想要我的item数据不实现MultiItemEntity怎么办?当然可以。

item不实现MultiItemEntity的多布局

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <variable
            name="vm"
            type="com.caesar.brvahbinding.nonMultiple.NonMultiViewModel" />
 
        <import type="com.caesarlib.brvahbinding.CSBrvahLayoutManager" />
    </data>
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".nonMultiple.NonMultipleActivity">
 
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{vm.onBack}"
            android:text="返回" />
 
        <androidx.recyclerview.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="4dp"
            app:cs_brvah_Decoration="@{vm.itemDecoration}"
            app:cs_brvah_adapter="@{vm.bindingAdapter}"
            app:cs_brvah_layoutManager="@{CSBrvahLayoutManager.grid(4)}"
            app:cs_brvah_multiType="@{vm.multiTypeDelegat}"
            app:cs_brvah_spansize="@{vm.spanSizeLookup}" />
    </LinearLayout>
</layout>
public class NonMultiViewModel extends BaseBindingViewModel<customData> {
    //在构造方法中,设置SpanSizeLookup,这个是每个item占几格的回调.MultiTypeDelegat这个是itemType的回调判断了,如果不想继承MultiItemEntity的话
    //就要由该回调来判断
    public NonMultiViewModel() {
        super();
        setSpan(new BaseQuickAdapter.SpanSizeLookup() {
            @Override
            public int getSpanSize(GridLayoutManager gridLayoutManager, int i) {
                if (items.get(i).getItemType() == 0) {
                    return 1;
                } else if (items.get(i).getItemType() == 1) {
                    return 2;
                } else if (items.get(i).getItemType() == 2) {
                    return 4;
                } else {
                    return 0;
                }
            }
        });
        setMultiTypeDelegat(new MultiTypeDelegate<customData>() {
            @Override
            protected int getItemType(customData customData) {
                return customData.getItemType();
            }
        });
    }
 
    @Override//这里面还是跟其他的一样
    protected Map<Integer, CSBravhItemBinding> getItemBinding() {
        Map<Integer, CSBravhItemBinding> mp = new HashMap<>();
        mp.put(0, new CSBravhItemBinding(com.caesar.brvahbinding.BR.data, R.layout.item_nomulti_zero));
        mp.put(1, new CSBravhItemBinding(com.caesar.brvahbinding.BR.data, R.layout.item_nomulti_one));
        mp.put(2, new CSBravhItemBinding(com.caesar.brvahbinding.BR.data, R.layout.item_nomulti_two));
        //这边的0,1,2要跟上面setMultiTypeDelegat返回的要对应起来
        return mp;
    }
 
    @Override
    public void load() {
        load(getData());
    }
 
    private Flowable<List<customData>> getData() {
        return Flowable.create(new FlowableOnSubscribe<List<customData>>() {
            @Override
            public void subscribe(FlowableEmitter<List<customData>> emitter) throws Exception {
                ArrayList<customData> data = new ArrayList<>();
                data.add(new NeoDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataOne("这货是个标题", "这货是个内容加描述", R.mipmap.head_img0));
                data.add(new NeoDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataTwo("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img2));
                data.add(new NeoDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataOne("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataOne("这货是个标题", "这货是个内容加描述", R.mipmap.head_img0));
                data.add(new NeoDataOne("这货是个标题", "这货是个内容加描述", R.mipmap.head_img0));
                data.add(new NeoDataTwo("这货是个标题", "这货是个内容加描述", R.mipmap.head_img2));
                data.add(new NeoDataOne("这货是个标题", "这货是个内容加描述", R.mipmap.head_img0));
                data.add(new NeoDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataTwo("这货是个标题", "这货是个内容加描述", R.mipmap.head_img2));
                data.add(new NeoDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataTwo("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataZero("这货是个标题", "这货是个内容加描述", R.mipmap.head_img1));
                data.add(new NeoDataOne("这货是个标题", "这货是个内容加描述", R.mipmap.head_img0));
                emitter.onNext(data);
                emitter.onComplete();
            }
        }, BackpressureStrategy.BUFFER);
    }
 
    @Override
    public RecyclerView.ItemDecoration onitemDecoration() {
        return new NormaltemDecoration(10);
    }
}
public class customData {//可以是接口,可以是类,只要有type类型判断
    public int itemType;
    public String title;
    public String discribe;
    public int imgRes;
 
    public customData(String title, String discribe, int imgRes) {
        this.title = title;
        this.discribe = discribe;
        this.imgRes = imgRes;
    }
 
    public int getItemType() {
        return itemType;
    }
 
    public void setItemType(int itemType) {
        this.itemType = itemType;
    }
 
    public String getTitle() {
        return title;
    }
 
    public void setTitle(String title) {
        this.title = title;
    }
 
    public String getDiscribe() {
        return discribe;
    }
 
    public void setDiscribe(String discribe) {
        this.discribe = discribe;
    }
 
    public int getImgRes() {
        return imgRes;
    }
 
    public void setImgRes(int imgRes) {
        this.imgRes = imgRes;
    }
}

大家看NonMultipleActivity这个类,界面没啥好讲。customData这个类中,有一个itemType,反正只要有一个可以判断item类型的参数就可以,在NonMultiViewModel的泛型中,写customData。在构造方法中,有一个setSpan()方法,这个方法就是适配器每个item占几个的回调,一般情况下,多布局Grid形式的,并且item所占格式不同的,基本都要回调这个方法,设置完该方法后,别忘记在布局中,用app:cs_brvah_spansize="@{vm.spanSizeLookup}"进行绑定。在构造方法中,还有一个setMultiTypeDelegat方法,这个方法就是设置每个item的类型的回调了,然后在布局文件中,通过app:cs_brvah_multiType="@{vm.multiTypeDelegat}"进行绑定,是不是特别简单。

文章太长了,大家请看下一章节。

转载请标明出处
BRVAH的BaseRecyclerViewAdapterHelper与MVVM模式优雅结合(其二)

BRVAH的BaseRecyclerViewAdapterHelper与MVVM模式优雅结合(其三)

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

推荐阅读更多精彩内容