BRVAH的BaseRecyclerViewAdapterHelper與MVVM模式優(yōu)雅結(jié)合(其一)
BRVAH的BaseRecyclerViewAdapterHelper與MVVM模式優(yōu)雅結(jié)合(其二)
好,在看本篇之前,請(qǐng)先看我寫的上面2個(gè)篇章。
上一章講了加載更多。這時(shí),就會(huì)有同學(xué)問:哎呀,古誠欺啊,那像聊天界面這種應(yīng)該怎么實(shí)現(xiàn)呢?
這你問對(duì)人了,我們接著往下說。
向下加載更多,仿聊天界面。話不多說,先上圖

public abstract class FetchLoadBindingViewModel<B> extends BaseBindingViewModel<B> {
//下拉監(jiān)聽回調(diào)
public BaseQuickAdapter.UpFetchListener upFetchListener;
public int mPage;
public int PageSize = 15;
public int defaultStart;
//其實(shí)就是一個(gè)item,我這邊為了保證聊天數(shù)據(jù)結(jié)構(gòu)完美,就寫在這了,用戶可以自己寫,這邊的item就是,聊天到頭的item
public FetchNomoreData fetchNomoreData = new FetchNomoreData();
//加載失敗的item,跟上面的一樣,也是一個(gè)itemType,也是要在綁定數(shù)據(jù)時(shí),要加上這個(gè)類別,作用是加載失敗時(shí)添加,點(diǎn)擊之后,重新加載.
public FetchErrorData fetchErrorData = new FetchErrorData();
public FetchLoadBindingViewModel(RecyclerView recyclerView) {
super();
this.mRecyclerView = recyclerView;
upFetchListener = getUpFetchListener();
emptyResId.set(getEmptyViewRes(EmptyViewType.LOADING));
bindingAdapter.setUpFetchEnable(true);
bindingAdapter.setStartUpFetchPosition(2);
}
protected BaseQuickAdapter.UpFetchListener getUpFetchListener() {
return new BaseQuickAdapter.UpFetchListener() {
@Override
public void onUpFetch() {
CSLog.Print("下拉加載更多了");
loadMore();
}
};
}
。。。
public class LoadMoreChatViewModel extends FetchLoadBindingViewModel<MultiItemEntity> {
private boolean isFirst = true;
//構(gòu)造函數(shù)中,有個(gè)列表參數(shù),目的是,當(dāng)?shù)谝淮渭虞d成功時(shí),滑到最下面
public LoadMoreChatViewModel(RecyclerView recyclerView) {
super(recyclerView);
}
//常規(guī)的綁定item,不過這邊加了另外2個(gè)item,加載到底和加載失敗的item,這部分用戶可以自己定義
@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_chat_left));
mp.put(1, new CSBravhItemBinding(com.caesar.brvahbinding.BR.data, R.layout.item_chat_right));
mp.put(30, new CSBravhItemBinding(com.caesar.brvahbinding.BR.data, R.layout.item_nomore_data));
mp.put(31, new CSBravhItemBinding(com.caesar.brvahbinding.BR.data, R.layout.item_fetch_error, com.caesar.brvahbinding.BR.action, new brvah()));
return mp;
}
//跟加載更多一樣
@Override
public void load(int mPage) {
if (mPage == 3) {
if (isFirst) {
isFirst = false;
load(getError());
} else {
load(getSimp());
}
} else if (mPage == 4) {
load(getLast());
} else {
load(getSimp());
}
}
。。。
}
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swp"
android:layout_width="match_parent"
app:refreshing="@{vm.isRefreshing}"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
app:cs_brvah_Decoration="@{vm.itemDecoration}"
app:cs_brvah_layoutManager="@{CSBrvahLayoutManager.fetLinear()}"
app:cs_brvah_adapter="@{vm.bindingAdapter}"
app:cs_brvah_emptyClickListener="@{vm.emptyOnClickListener}"
app:cs_brvah_emptyResId="@{vm.emptyResId}"
app:cs_brvah_upFetchListener="@{vm.upFetchListener}" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
眼尖的同學(xué),是不是已經(jīng)發(fā)現(xiàn)了,下拉加載的viewModel是繼承FetchLoadBindingViewModel的,大致一看,F(xiàn)etchLoadBindingViewModel跟LoadMoreBindingViewModel是不是差不多。不過,一個(gè)是上拉加載更多,一個(gè)是下拉加載更多。
其中BaseQuickAdapter.UpFetchListener upFetchListener就是下拉的監(jiān)聽回調(diào)了。有些細(xì)節(jié)說一下,bindingAdapter.setStartUpFetchPosition(2)這個(gè)是設(shè)置從第幾個(gè)item開始加載,然后調(diào)用bindingAdapter.setUpFetchEnable(true)就開啟支持下拉加載功能。
好,然后我們看LoadMoreChatViewModel,在構(gòu)造方法的時(shí)候,傳了一個(gè)Recyclerview參數(shù),該作用就是,在第一次加載完成的時(shí)候,能夠使Recyclerview滑到最下面。
然后我們看布局文件,是不是還是千篇一律,綁定對(duì)應(yīng)的屬性就OK了。就只要綁定app:cs_brvah_upFetchListener="@{vm.upFetchListener}"就OK了
如果我想要在2個(gè),乃至多個(gè)列表中使用,又應(yīng)該怎么辦?
同學(xué),你這個(gè)問題問得很好,作為古誠欺,我又怎么可能會(huì)沒有考慮到呢。
雙布局綁定,仿外賣界面

public abstract class TwoListBindingViewModel<A, B> extends BaseViewModel {
//第一個(gè)列表的屬性
//數(shù)據(jù)集
public ObservableArrayList<A> itemsA;
//數(shù)據(jù)綁定的布局及BR和data
public Map<Integer, CSBravhItemBinding> itemBindingA;
//適配器,可以用用戶自己的,但是必須要繼承CSItemBindingAdapter
public CSItemBindingAdapter<A, BaseViewHolder> bindingAdapterA;
//設(shè)置每個(gè)item的占的格數(shù)
public BaseQuickAdapter.SpanSizeLookup spanSizeLookupA;
//當(dāng)多布局時(shí),如果item不想繼承MultiItemEntity,可以用這個(gè)來設(shè)置每個(gè)itemType
。。。
//第二個(gè)列表的屬性
//數(shù)據(jù)集
public ObservableArrayList<B> itemsB;
//數(shù)據(jù)綁定的布局及BR和data
public Map<Integer, CSBravhItemBinding> itemBindingB;
//適配器,可以用用戶自己的,但是必須要繼承CSItemBindingAdapter
public CSItemBindingAdapter<B, BaseViewHolder> bindingAdapterB;
//設(shè)置每個(gè)item的占的格數(shù)
。。。
public TwoListBindingViewModel() {
itemsA = new ObservableArrayLi
。。。
<android.support.v7.widget.RecyclerView
android:layout_width="0dp"
app:cs_brvah_adapter="@{vm.bindingAdapterA}"
android:layout_weight="1"
android:layout_height="match_parent" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_show"
app:cs_brvah_adapter="@{vm.bindingAdapterB}"
android:layout_width="0dp"
android:layout_weight="3"
android:layout_height="match_parent" />
大家看TwoListActivity界面,東西實(shí)在是簡單,跟單列表的差不多,你2個(gè)列表,那不就是綁定的屬性,多一倍么,是不是這個(gè)理,3個(gè)列表那就3倍。
可以看到,viewModel是繼承TwoListBindingViewModel的,這時(shí)要傳2個(gè)泛型了,列表1和列表2的數(shù)據(jù)類型。viewModel里面的內(nèi)容實(shí)在太簡單了,我這邊就不貼了,看一下布局,恩,就是這么簡單。好
這時(shí),就有同學(xué)發(fā)問了:那我以前寫了很多的適配器,難道就沒用了么,讓我放棄使用他們,我不舍得啊。
我就知道你會(huì)這么想,你放心,我已經(jīng)考慮過這種情況,你仍舊可以使用你自己的適配器來實(shí)現(xiàn)快捷的綁定。
使用自己的適配器來集成
當(dāng)然,前提是,你的適配器,是集成BRVAH的萬能適配器。
public class CustomAdapterViewModel extends BaseBindingViewModel<SimpleData> {
public CustomAdapter customAdapter;
//在viewModel中,初始化自己的構(gòu)造器
public CustomAdapterViewModel() {
super();
customAdapter = new CustomAdapter(R.layout.item_simple, items);
customAdapter.isFirstOnly(false);
}
//因?yàn)槭怯米约旱倪m配器,所以這個(gè)返回為空
@Override
protected Map<Integer, CSBravhItemBinding> getItemBinding() {
return null;
}
@Override
public void load() {
load(CreateData.getSimpleData());
}
//因?yàn)樽约旱倪m配器沒有監(jiān)聽items的改變事件,所以不會(huì)主動(dòng)去刷新適配器,所以在數(shù)據(jù)加載完成的回調(diào)中,要主動(dòng)刷新適配器.
@Override
public void onDataLoadComplete() {
customAdapter.notifyDataSetChanged();
}
@Override
public RecyclerView.ItemDecoration onitemDecoration() {
return new NormalLineDecoration(30, true);
}
}
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_show"
android:layout_width="match_parent"
app:cs_brvah_animation="@{vm.animationType}"
android:layout_height="match_parent"
app:cs_brvah_Decoration="@{vm.itemDecoration}"
app:cs_brvah_adapter="@{vm.customAdapter}"
/>
大家找到CustomAdapterActivity這個(gè)界面,我自己新建了一個(gè)適配器為CustomAdapter,里面實(shí)現(xiàn)了databinding的數(shù)據(jù)綁定,然后在我的viewModel中初始化。因?yàn)槭亲约旱倪m配器,所以getItemBinding這個(gè)方法就可以返回為空,然后因?yàn)檫m配器沒有監(jiān)聽列表數(shù)據(jù)的變化監(jiān)聽,所以在onDataLoadComplete每次數(shù)據(jù)加載完成的時(shí)候,都要去主動(dòng)刷新它。其他的屬性設(shè)置都是一樣的,最后看布局代碼。原先綁定適配器是app:cs_brvah_adapter="@{vm.bindingAdapter}",現(xiàn)在因?yàn)槟闶鞘褂米约旱倪m配器,所以只要app:cs_brvah_adapter="@{vm.customAdapter}"綁定你自己的適配器就可以了,Soeasy。
側(cè)滑列表
先放圖說話

該功能很簡單,在我的框架中,有一個(gè)CSBrvahLayoutManager類,里面就可以設(shè)置Recyclerview的顯示方式,這個(gè)在上面的grid顯示中有用到,橫劃我們用到的是linear(@RecyclerView.Orientation final int orientation, final boolean reverseLayout) 這個(gè)方法,大家可以看HorlzonActivity這個(gè)界面,很簡單,跟普通的一樣,我這邊就不寫了,只寫一下布局中調(diào)用。
<data>
<variable
name="vm"
type="com.caesar.brvahbinding.horizontal.HorlzonViewModel" />
<import type="com.caesarlib.brvahbinding.CSBrvahLayoutManager" />
<import type="androidx.recyclerview.widget.RecyclerView"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".horizontal.HorlzonActivity">
。。。
<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_layoutManager="@{CSBrvahLayoutManager.linear(RecyclerView.HORIZONTAL,false)}" />
</LinearLayout>
在布局文件中,我們導(dǎo)入com.caesarlib.brvahbinding.CSBrvahLayoutManager和androidx.recyclerview.widget.RecyclerView,然后在RecyclerView中,通過app:cs_brvah_layoutManager屬性添加CSBrvahLayoutManager.linear,其中第二個(gè)布爾參數(shù),是設(shè)置你列表從尾部開始顯示,默認(rèn)為false。
好了,以上就是我MVVM綁定萬能適配器插件的全部內(nèi)容,如果有不清楚的,可以留言咨詢我。
BRVAH的BaseRecyclerViewAdapterHelper與MVVM模式優(yōu)雅結(jié)合(其一)
BRVAH的BaseRecyclerViewAdapterHelper與MVVM模式優(yōu)雅結(jié)合(其二)