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閱讀 227,967評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,815評論 2 372

推薦閱讀更多精彩內容