来了!他来了!支持MVVM的BRVAH来了!

本文介绍了如何将BaseRecyclerViewAdapterHelper与MVVM模式结合起来,创建一个名为CSBrvahBinding的控件,简化Android列表开发,减少适配器和bean类的编写,提升代码的简洁性和优雅性。内容包括控件的使用前提、功能特点、多布局支持、自定义动画、头部和脚部的 databinding 添加等,适用于MVVM模式的项目。
摘要由CSDN通过智能技术生成

码个蛋(codeegg) 第 903 次推文

作者:古诚欺

博客:https://blog.csdn.net/Shaojihan/article/details/103673399

先一句话描述这个控件的功能:

将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一起看才相得益彰。希望大家能耐心看完,之后,你会觉得该控件真心赞,帮你项目开发更加精简)

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

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

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

首页样式    

例子列表截图:

首页列表调用方式:

非常简单,这个是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模式

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);
    }
}

大家先看布局文件,有一个

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}"进行绑定,是不是特别简单。

相关文章:

今日问题:

大家开始用MVVM了吗?

专属升级社区:《这件事情,我终于想明白了》 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值