美文网首页Android开发
BRVAH的BaseRecyclerViewAdapterHel

BRVAH的BaseRecyclerViewAdapterHel

作者: 古诚欺 | 来源:发表于2020-01-11 21:20 被阅读0次

    BRVAH的BaseRecyclerViewAdapterHelper与MVVM模式优雅结合(其一)
    BRVAH的BaseRecyclerViewAdapterHelper与MVVM模式优雅结合(其三)
    接上一章内容,如果大家没有看过第一章的话,请先看第一章。点上面链接就能跳转。

    头部和脚部

    20191225102453646.gif
    public class HeadFootViewModel 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//这个回调是头部的item的绑定数据,也支持绑定多个数据事件
        public ArrayList<CSBravhItemBinding> getHeadBinding() {
            ArrayList<CSBravhItemBinding> heads = new ArrayList<>();
            heads.add(new CSBravhItemBinding(BR.data, R.layout.layout_head_one, new HeadOneData(), BR.action, new brvah()));
            heads.add(new CSBravhItemBinding(BR.data, R.layout.layout_head_two, new HeadTwoData()));
            return heads;
        }
     
        @Override//这个回调是脚部的item的绑定数据,也支持绑定多个数据事件
        public ArrayList<CSBravhItemBinding> getFootBinding() {
            ArrayList<CSBravhItemBinding> foots = new ArrayList<>();
            foots.add(new CSBravhItemBinding(BR.data, R.layout.layout_foot_one, new FootOneData()));
            foots.add(new CSBravhItemBinding(BR.data, R.layout.layout_foot_two, new FootTwoData()));
            return foots;
        }
     
        @Override
        public void load() {
            load(CreateData.getSimpleData());
        }
     
        @Override
        public RecyclerView.ItemDecoration onitemDecoration() {
            return new NormalLineTopHeadDecoration(30, true);
        }
     
        //某个头部绑定的事件,告诉大家可以这样调用
        public class brvah implements CSAction0 {
            @Override
            public void call() {
                bindingAdapter.removeAllHeaderView();
            }
        }
    }
    

    先看布局文件,很简单,app:cs_brvah_footBinding="@{vm.footBinding}" app:cs_brvah_headBinding="@{vm.headBinding}"这2个方法,分别绑定了头部和脚部。接着,大家看HeadFootViewModel这个类,其中getHeadBinding()这个回调,是绑定头部的,跟普通的item绑定很像,只是少了个itemType,里面传布局跟data,也可以绑定其他的事件。同理脚部布局数据是getFootBinding()这个回调。是不是很简单。

    空布局和下拉刷新

      <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:OnRefreshListener="@{vm.refreshListener}"
                app:refreshing="@{vm.isRefreshing}">
     
                <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_emptyClickListener="@{vm.emptyOnClickListener}"
                    app:cs_brvah_emptyResId="@{vm.emptyResId}" />
            </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
    
    public class EmptyRefrshViewModel extends BaseBindingViewModel<SimpleData> {
     
        private int countD;
     
        @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() {
            ++countD;
            if (countD % 3 == 0) {
                load(CreateData.getSimpleData());
            } else if (countD % 3 == 1) {
                load(getEmptyData());
            } else if (countD % 3 == 2) {
                load(getErrorData());
            }
     
        }
        //模拟数据返回为空
        public static Flowable<List<SimpleData>> getEmptyData() {
            CSLog.Print("调用加载空布局");
            return Flowable.create(new FlowableOnSubscribe<List<SimpleData>>() {
                @Override
                public void subscribe(FlowableEmitter<List<SimpleData>> emitter) throws Exception {
                    ArrayList<SimpleData> data = new ArrayList<>();
                    emitter.onNext(data);
                    emitter.onComplete();
                }
            }, BackpressureStrategy.BUFFER).delay(3, TimeUnit.SECONDS);
        }
        //模拟网络请求出错
        public static Flowable<List<SimpleData>> getErrorData() {
            CSLog.Print("调用加载错误");
            return Flowable.create(new FlowableOnSubscribe<List<SimpleData>>() {
                @Override
                public void subscribe(FlowableEmitter<List<SimpleData>> emitter) throws Exception {
                    emitter.onError(null);
                }
            }, BackpressureStrategy.BUFFER).delay(1, TimeUnit.SECONDS);
        }
        //清空数据的点击事件,这边因为我的baseAdapter里面,对items做过监听,可以看CSBindingListChangedCallBack这个类,所以,当items的数据发生
        //改变时,绑定的适配器会自动刷新,所以,如果你是使用自己的适配器的话(下面会讲),别忘记刷新适配器
        public void cliear(View view) {
            items.clear();
        }
     
        @Override
        public RecyclerView.ItemDecoration onitemDecoration() {
            return new NormalLineDecoration(30, true);
        }
     
        @Override//可以重写空布局的UI
        public int getEmptyViewRes(int type) {
            switch (type) {
                case EmptyViewType.ERROR:
                    return R.layout.layout_frame_error_view;
                case EmptyViewType.LOADING:
                    return R.layout.layout_frame_loading_view;
                case EmptyViewType.REFRESH:
                    return R.layout.layout_frame_refresh_view;
                default:
                    return R.layout.layout_frame_empty_view;
            }
        }
    }
    

    大家找到EmptyRefreshActivity这个界面,在布局文件中,我加了一个SwipeRefreshLayout下拉刷新控件,在里面,绑定了app:OnRefreshListener="@{vm.refreshListener}"和app:refreshing="@{vm.isRefreshing}",其中refreshListener这个是下拉监听器,我的baseViewModel中,写了监听回调,

    //下拉刷新控件的监听器,里面调用重新加载数据的方法
        public SwipeRefreshLayout.OnRefreshListener getRefreshListener() {
            return new SwipeRefreshLayout.OnRefreshListener() {
                @Override
                public void onRefresh() {
                    isRefreshing.set(true);
                    reload();
                }
            };
        }
    

    如果下拉了,就会调用重新加载的方法。而isRefreshing这个是刷新判断,因为跟下拉控件绑定在一起,所以下拉的时候,可以反应刷新控件的状态。然后在RecyclerView中,我绑定了app:cs_brvah_emptyClickListener="@{vm.emptyOnClickListener}" 和app:cs_brvah_emptyResId="@{vm.emptyResId}",第一个是绑定空布局的点击事件,下面是baseViewModel的部分相关代码

    //空布局的点击事件,里面做判断,如果当前空布局不是正在加载的状态,点击之后,就重新获取数据
        protected View.OnClickListener getEmptyOnClickListener() {
            return new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    CSLog.Print("点击了空布局按钮");
                    if (emptyResId.get() != getEmptyViewRes(EmptyViewType.LOADING)) {
                        reload();
                        emptyResId.set(getEmptyViewRes(EmptyViewType.LOADING));
                    }
                }
            };
        }
    

    当点击空布局时,如果当前不是正在加载的状态,就重新获取数据。

    第二个vm.emptyResId是空布局的绑定,你可以在每个viewModel中,重写getEmptyViewRes这个方法,就可以定制空布局了。

    侧滑删除和拖动

    20191225102629532.gif

    好,先来讲侧滑删除,大家找到SwipeActivity这个界面

    public class SwipeViewModel extends BaseBindingViewModel<SimpleData> {
        private boolean isSwipe = true;
     
       。。。
     
        @Override//只要重写这个监听器,然后再布局中绑定,就能侧滑删除
        public OnItemSwipeListener getItemSwipeListener() {
            return new OnItemSwipeListener() {
                @Override
                public void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int i) {
     
                }
     
                @Override
                public void clearView(RecyclerView.ViewHolder viewHolder, int i) {
     
                }
     
                @Override
                public void onItemSwiped(RecyclerView.ViewHolder viewHolder, int i) {
     
                }
     
                @Override
                public void onItemSwipeMoving(Canvas canvas, RecyclerView.ViewHolder viewHolder, float v, float v1, boolean b) {
                    canvas.drawColor(ContextCompat.getColor(FramGroble.INSTANCE.getTopActivity(), R.color.colorAccent));
                }
            };
        }
    //这边是一个控制侧滑开关的例子,通过获取Controller()来控制,我已经在适配器中封装好了
        public void onSwi(View view) {
            if (isSwipe) {
                isSwipe = false;
                bindingAdapter.getDraggableController().disableSwipeItem();
            } else {
                isSwipe = true;
                bindingAdapter.getDraggableController().enableSwipeItem();
            }
        }
     
        @Override//设置侧滑方向
        public int getOnSwipeMoveFrags() {
            return ItemTouchHelper.START | ItemTouchHelper.END;
        }
    }
    
    <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv_show"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:cs_brvah_SwipeMoveFrags="@{vm.swipeMoveFrags}"
                app:cs_brvah_Decoration="@{vm.itemDecoration}"
                app:cs_brvah_OnItemSwipeListener="@{vm.onItemSwipeListener}"
                app:cs_brvah_adapter="@{vm.bindingAdapter}"
     
                />
    

    是不是也很简单,首先看viewModel,只要你重写了OnItemSwipeListener这个监听回调,然后在布局文件中,将该监听器绑定在布局中,app:cs_brvah_OnItemSwipeListener="@{vm.onItemSwipeListener}"就可以了,是不是很简单。然后你还可以设置滑动的方向,默认是向后滑动删除的,你可以通过getOnSwipeMoveFrags()重写这个方法,进行设置,当然设置好了之后,别忘了在布局文件中去绑定。如果你想要设置滑动开关怎么办,那当然也是可以的,万能适配器通过一个Controller来进行控制,我已经封装在适配器里了,你可以通过bindingAdapter.getDraggableController()获取到,然后设置开关就可以,例子已经给出。

    接下来是拖动功能

    public class DragViewModel extends NonMultiViewModel {
     
        private boolean isSwipe = true;
     
        @Override//只要设置拖动监听器,就可以实现拖动功能
        public OnItemDragListener getItemDragListener() {
            return new OnItemDragListener() {
                @Override
                public void onItemDragStart(RecyclerView.ViewHolder viewHolder, int i) {
     
                }
     
                @Override
                public void onItemDragMoving(RecyclerView.ViewHolder viewHolder, int i, RecyclerView.ViewHolder viewHolder1, int i1) {
     
                }
     
                @Override
                public void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int i) {
     
                }
            };
        }
    //拖动开关
        public void onSwi(View view) {
            if (isSwipe) {
                isSwipe = false;
                bindingAdapter.getDraggableController().disableDragItem();
            } else {
                isSwipe = true;
                bindingAdapter.getDraggableController().enableDragItem(bindingAdapter.getItemTouchHelper(null));
            }
        }
    }
    
    <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv_show"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:cs_brvah_Decoration="@{vm.itemDecoration}"
                app:cs_brvah_OnItemDragListener="@{vm.onItemDragListener}"
                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}"
     
                />
    

    我这边拖动的viewModel,继承了另外一个NonMultiViewModel,因为界面是一样的。拖动跟侧滑很像,也只要重写getItemDragListener监听器就可以,然后在布局中,调用app:cs_brvah_OnItemDragListener="@{vm.onItemDragListener}"进行绑定。是不是超级简单。拖动的开关控制器,跟侧滑一样,也是调用getDraggableController(),不过打开拖动功能的时候,要注意bindingAdapter.getDraggableController().enableDragItem()里面要传一个Touch,这个touch要通过bindingAdapter.getItemTouchHelper(null)方法去获取,因为在绑定的时候,已经生成了一个touch,可以保证唯一性。例子里面都有。

    我这边将拖动跟侧滑功能合在一起,做了个例子,大家可以找到DragASwipeActivity这个类,调用方法是一模一样的,我这里就不再重复了。

    Expand可扩展的多布局

    20191225120822709.gif
    public class ExpandViewModel extends BaseBindingViewModel<MultiItemEntity> {
     
        。。。
    //当每次数据加载完成的时候,都会回调该方法,我在这边,将列表展开
        @Override
        public void onDataLoadComplete() {
            bindingAdapter.expandAll();
        }
     
        //模拟获取数据,这边的数据要继承AbstractExpandableItem
        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<>();
                    for (int i = 0; i < 5; i++) {
                        ExDataGrandFa exDataGrandFa = new ExDataGrandFa("点我有惊喜", "点我啊", R.mipmap.headerandfooter_img1);
                        for (int j = 0; j < 3; j++) {
                            ExDataFather exDataFather = new ExDataFather("点我啊", "来点我啊", R.mipmap.m_img1);
                            for (int k = 0; k < 6; k++) {
                                ExDataChild exDataChild = new ExDataChild("点我消失", R.mipmap.head_img1);
                                exDataFather.addSubItem(exDataChild);
                            }
                            exDataGrandFa.addSubItem(exDataFather);
                        }
                        data.add(exDataGrandFa);
                    }
                    emitter.onNext(data);
                    emitter.onComplete();
                }
            }, BackpressureStrategy.BUFFER);
        }
     
        @Override
        public RecyclerView.ItemDecoration onitemDecoration() {
            return new NormaltemDecoration(10);
        }
     
        //最外面item的点击事件,里面调用item的扩展和收缩.
        public class GrandAct implements CSAction1<ExDataGrandFa> {
     
            @Override
            public void call(ExDataGrandFa param) {
                if (param.isExpanded()) {
                    bindingAdapter.collapse(items.indexOf(param));
                } else {
                    bindingAdapter.expand(items.indexOf(param));
                }
            }
        }
     
        //第二个item的点击事件,调用里面item的扩展和说收缩
        public class FatherAct implements CSAction1<ExDataFather> {
     
            @Override
            public void call(ExDataFather param) {
                if (param.isExpanded()) {
                    bindingAdapter.collapse(items.indexOf(param));
                } else {
                    bindingAdapter.expand(items.indexOf(param));
                }
            }
        }
     
        //最里面item的点击事件,将item从本列表中删除,记住有2个地方要删除,一个是items,第二个是它外层的item中的数据
        public class ChildAct implements CSAction1<ExDataChild> {
            @Override
            public void call(ExDataChild param) {
                //这一部分删除其实也不难,我是直接抄官方的,先获取当前item的父item,将集合中item去掉,再从父item中删掉当前item,要删2次
                int positionAtAll = getParentPositionInAll(items.indexOf(param));
                items.remove(param);
                if (positionAtAll != -1) {
                    IExpandable multiItemEntity = (IExpandable) bindingAdapter.getData().get(positionAtAll);
                    multiItemEntity.getSubItems().remove(param);
                }
            }
        }
     
     
        /**
         * 该方法用于 IExpandable 树形列表。
         * 如果不存在 Parent,则 return -1。
         *
         * @param position 所处列表的位置
         * @return 父 position 在数据列表中的位置
         */
        public int getParentPositionInAll(int position) {
            List<MultiItemEntity> data = bindingAdapter.getData();
            MultiItemEntity multiItemEntity = bindingAdapter.getItem(position);
     
            if (isExpandable(multiItemEntity)) {
                IExpandable IExpandable = (IExpandable) multiItemEntity;
                for (int i = position - 1; i >= 0; i--) {
                    MultiItemEntity entity = data.get(i);
                    if (isExpandable(entity) && IExpandable.getLevel() > ((IExpandable) entity).getLevel()) {
                        return I;
                    }
                }
            } else {
                for (int i = position - 1; i >= 0; i--) {
                    MultiItemEntity entity = data.get(i);
                    if (isExpandable(entity)) {
                        return I;
                    }
                }
            }
            return -1;
        }
     
        public boolean isExpandable(MultiItemEntity item) {
            return item != null && item instanceof IExpandable;
        }
     
    }
    

    布局的代码没什么好说的,就是常规调用,来看一下viewModel,是不是跟普通的多布局很像,也是实现了MultiItemEntity,不同的地方就是,它的item要继承AbstractExpandableItem这个类,跟BRVAH中的一样,其中的action是我写的每个item的点击事件监听。也很简单。

    下拉刷新,上拉加载

    20191225130722781.gif

    下拉上拉这一部分用的还是挺多的,所以我要稍微着重讲解一下,先贴代码

    public abstract class LoadMoreBindingViewModel<B> extends BaseBindingViewModel<B> {
     
        //加载更多布局,可以自定义
        public LoadMoreView loadMoreView;
        //加载更多结束
        public ObservableBoolean loadMoreEnd;
        //是否能够加载更多
        public ObservableBoolean loadMoreEnable;
        //加载更多完成
        public ObservableBoolean loadMoreSuccess;
        //上拉加载的监听回调
        public BaseQuickAdapter.RequestLoadMoreListener loadMoreListener;
        //当前页数,默认从0开始,可以设置默认值
        public int mPage;
        //每页加载返回的个数,按照这个来判断是否已经加到头了
        public int PageSize = 15;
        //默认从第几页开始加载
        public int defaultStart;
     
        public LoadMoreBindingViewModel() {
            super();
            loadMoreView = getLoadMoreView();
            loadMoreListener = getLoadMoreListener();
            loadMoreEnd = new ObservableBoolean();
            loadMoreEnable = new ObservableBoolean();
            loadMoreSuccess = new ObservableBoolean();
        }
     
     
        protected LoadMoreView getLoadMoreView() {
            return new LoadMoreView() {
                @Override
                public int getLayoutId() {
                    return R.layout.view_load_more;
                }
     
                @Override
                protected int getLoadingViewId() {
                    return R.id.load_more_loading_view;
                }
     
                @Override
                protected int getLoadFailViewId() {
                    return R.id.load_more_load_fail_view;
                }
     
                @Override
                protected int getLoadEndViewId() {
                    return R.id.load_more_load_end_view;
                }
            };
        }
     
        protected BaseQuickAdapter.RequestLoadMoreListener getLoadMoreListener() {
            return new BaseQuickAdapter.RequestLoadMoreListener() {
                @Override
                public void onLoadMoreRequested() {
                    loadMore();
                }
            };
        }
     
     
        private void loadMore() {
            CSLog.Print("加载更多调用了");
            load();
        }
     
     
        @Override
        public void load() {
            load(mPage);
        }
     
        @Override
        protected void load(Flowable<List<B>> flowable) {
            if (isRefreshing.get()) {
                emptyResId.set(getEmptyViewRes(EmptyViewType.REFRESH));
            } else {
                CSLog.Print("调用了正在加载界面");
                emptyResId.set(getEmptyViewRes(EmptyViewType.LOADING));
            }
            disposable = flowable.observeOn(AndroidSchedulers.mainThread())
                    .subscribeOn(Schedulers.io())
                    .subscribe(new Consumer<List<B>>() {
                        @Override
                        public void accept(List<B> result) throws Exception {
                            setData(result);
                        }
                    }, new Consumer<Throwable>() {
                        @Override
                        public void accept(Throwable throwable) throws Exception {
                            if (isRefreshing.get() || mPage == defaultStart) {
                                emptyResId.set(getEmptyViewRes(EmptyViewType.ERROR));
                                loadMoreEnable.set(true);
                            } else {
                                loadMoreSuccess.set(false);
                                loadMoreSuccess.notifyChange();
                            }
                            isRefreshing.set(false);
                        }
                    }, new Action() {
                        @Override
                        public void run() throws Exception {
                            loadMoreEnable.set(true);
                            emptyResId.set(getEmptyViewRes(EmptyViewType.EMPTY));
                            isRefreshing.set(false);
                            mPage++;
                        }
                    });
        }
     
        //重新加载,页数清空
        @Override
        public void reload() {
            mPage = defaultStart;
            super.reload();
        }
     
        //设置默认从第几页开始加载
        public void setDefaultStart(int index) {
            defaultStart = index;
            mPage = index;
        }
     
     
        public void setData(List<B> dat) {
            addItems(dat);
            if (dat.size() < getPageSize()) {
                loadMoreEnd.set(mPage == defaultStart);
                loadMoreEnd.notifyChange();
            } else {
                loadMoreSuccess.set(true);
                loadMoreSuccess.notifyChange();
            }
        }
     
        public abstract void load(int mPage);
     
        public int getPageSize() {
            return PageSize;
        }
     
        public void setPageSize(int pageSize) {
            this.PageSize = pageSize;
        }
    }
    
    public class LoadMoreLineViewModel extends LoadMoreBindingViewModel<SimpleData> {
        private boolean isFirst = true;
    //构造方法中,设置每页获取的个数,这个值是用来判断当前网络请求,是否是最后一页的数据
        public LoadMoreLineViewModel() {
            super();
            setPageSize(10);
        }
     
        @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(int mPage) {
            CSLog.Print("当前加载的页:" + mPage);
            if (mPage == 2) {
                if (isFirst) {
                    isFirst = false;
                    load(getErr());
                } else {
                    load(getSimp());
                }
            } else if (mPage == 3) {
                load(getFsa());
            } else {
                load(getSimp());
            }
        }
     
     
        public Flowable<List<SimpleData>> getSimp() {
            return Flowable.create(new FlowableOnSubscribe<List<SimpleData>>() {
                @Override
                public void subscribe(FlowableEmitter<List<SimpleData>> emitter) throws Exception {
                    ArrayList<SimpleData> data = new ArrayList<>();
                    data.add(new SimpleData("这货是个标题", "这货是个内容加描述", R.mipmap.animation_img1));
                    data.add(new SimpleData("这货是个标题", "这货是个内容加描述", R.mipmap.animation_img2));
                    data.add(new SimpleData("这货是个标题", "这货是个内容加描述", R.mipmap.animation_img3));
                    data.add(new SimpleData("这货是个标题", "这货是个内容加描述", R.mipmap.animation_img2));
                    data.add(new SimpleData("这货是个标题", "这货是个内容加描述", R.mipmap.animation_img1));
                    data.add(new SimpleData("这货是个标题", "这货是个内容加描述", R.mipmap.animation_img3));
                    data.add(new SimpleData("这货是个标题", "这货是个内容加描述", R.mipmap.animation_img2));
                    data.add(new SimpleData("这货是个标题", "这货是个内容加描述", R.mipmap.animation_img1));
                    data.add(new SimpleData("这货是个标题", "这货是个内容加描述", R.mipmap.animation_img3));
                    data.add(new SimpleData("这货是个标题", "这货是个内容加描述", R.mipmap.animation_img2));
                    emitter.onNext(data);
                    emitter.onComplete();
                }
            }, BackpressureStrategy.BUFFER).delay(3, TimeUnit.SECONDS);
        }
     
     
        public Flowable<List<SimpleData>> getErr() {
            return Flowable.create(new FlowableOnSubscribe<List<SimpleData>>() {
                @Override
                public void subscribe(FlowableEmitter<List<SimpleData>> emitter) throws Exception {
                    emitter.onError(null);
                }
            }, BackpressureStrategy.BUFFER).delay(3, TimeUnit.SECONDS);
        }
     
        public Flowable<List<SimpleData>> getFsa() {
            return Flowable.create(new FlowableOnSubscribe<List<SimpleData>>() {
                @Override
                public void subscribe(FlowableEmitter<List<SimpleData>> emitter) throws Exception {
                    ArrayList<SimpleData> data = new ArrayList<>();
                    data.add(new SimpleData("这货是个标题", "这货是个内容加描述", R.mipmap.animation_img1));
                    data.add(new SimpleData("这货是个标题", "这货是个内容加描述", R.mipmap.animation_img2));
                    emitter.onNext(data);
                    emitter.onComplete();
                }
            }, BackpressureStrategy.BUFFER).delay(3, TimeUnit.SECONDS);
        }
     
        @Override
        public RecyclerView.ItemDecoration onitemDecoration() {
            return new NormalLineDecoration(30, true);
        }
     
    }
    
     <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:OnRefreshListener="@{vm.refreshListener}"
                app:refreshing="@{vm.isRefreshing}">
     
                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/rv_show"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:padding="5dp"
                    app:cs_brvah_Decoration="@{vm.itemDecoration}"
                    app:cs_brvah_emptyResId="@{vm.emptyResId}"
                    app:cs_brvah_emptyClickListener="@{vm.emptyOnClickListener}"
                    app:cs_brvah_adapter="@{vm.bindingAdapter}"
                    app:cs_brvah_loadMoreEnd="@{vm.loadMoreEnd}"
                    app:cs_brvah_loadMoreEnable="@{vm.loadMoreEnable}"
                    app:cs_brvah_loadMoreListener="@{vm.loadMoreListener}"
                    app:cs_brvah_loadMoreSuccess="@{vm.loadMoreSuccess}"
                    app:cs_brvah_loadMoreView="@{vm.loadMoreView}"
     
                    />
            </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
    

    好,大家先找到LoadMoreLineActivity界面,仔细的同学就会发现,这边的viewModel我继承的是LoadMoreBindingViewModel,而LoadMoreBindingViewModel又是继承BaseBindingViewModel。

    我们先看LoadMoreBindingViewModel,里面,新增加了一些属性,有LoadMoreView loadMoreView,这个是上拉加载的动画,可以用户自己定制,只要重写getLoadMoreView方法就可以了。bservableBoolean loadMoreEnd这个是判断是否已经加载结束。其中最关键的是新增的属性mPage,加载更多是有页数的,所以mPage这个值,就表示当前加载的是第几页,默认0,也可以设置从第1页开始加载。PageSize这个属性是判断是否已经加载到尾部,如果你加载回来的个数,小于这个值,就表示已经加载到头了。defaultStart这个值,是判断初始是从第几页开始加载。

    好,接下来我们来看看LoadMoreLineViewModel这个类,其实也简单,就是一些常规的调用,不过原先重写的load()回调中,里面加了一个int mpage参数,这个就是当前加载的页数。然后数据请求加载的方式,跟原先的是一样的。

    最后来看一下布局文件的代码。下拉刷新控件的绑定我上面已经讲过了,这边就不讲了,主要是列表的绑定,如果你是想要你的布局支持加载更多的话,其中,app:cs_brvah_loadMoreEnd="@{vm.loadMoreEnd}" app:cs_brvah_loadMoreEnable="@{vm.loadMoreEnable}" app:cs_brvah_loadMoreListener="@{vm.loadMoreListener}" app:cs_brvah_loadMoreSuccess="@{vm.loadMoreSuccess}"app:cs_brvah_loadMoreView="@{vm.loadMoreView}"

    是必须要加的,判断加载状态,加载监听,加载时的动画等等,直接照写就完事。

      @BindingAdapter(value = {"cs_brvah_loadMoreEnd"})
        public static void onLoadMoreEnd(RecyclerView recyclerView, ObservableBoolean loadMoreEnd) {
            CSLog.Print("加载结束调用:" + loadMoreEnd.get());
            RecyclerView.Adapter adapter = recyclerView.getAdapter();
            if (adapter instanceof BaseQuickAdapter) {
                CSLog.Print("进入加载结束调用:" + loadMoreEnd.get());
                ((BaseQuickAdapter) adapter).loadMoreEnd(loadMoreEnd.get());
            }
        }
     
        @BindingAdapter(value = {"cs_brvah_loadMoreEnable"})
        public static void onLoadMoreEnable(RecyclerView recyclerView, ObservableBoolean loadMoreEnable) {
            CSLog.Print("是否加载更多:" + loadMoreEnable.get());
            RecyclerView.Adapter adapter = recyclerView.getAdapter();
            if (adapter instanceof BaseQuickAdapter) {
                CSLog.Print("进入是否加载更多:" + loadMoreEnable.get());
                ((BaseQuickAdapter) adapter).setEnableLoadMore(loadMoreEnable.get());
            }
        }
     
        @BindingAdapter(value = {"cs_brvah_loadMoreSuccess"})
        public static void onLoadMoreSuccess(RecyclerView recyclerView, ObservableBoolean loadMoreSuccess) {
            CSLog.Print("是否加载成功:" + loadMoreSuccess.get());
            RecyclerView.Adapter adapter = recyclerView.getAdapter();
            if (adapter instanceof BaseQuickAdapter) {
                CSLog.Print("进入是否加载成功:" + loadMoreSuccess.get());
                if (loadMoreSuccess.get()) {
                    ((BaseQuickAdapter) adapter).loadMoreComplete();
                } else {
                    ((BaseQuickAdapter) adapter).loadMoreFail();
                }
            }
        }
     
     
        @BindingAdapter(value = {"cs_brvah_emptyResId", "cs_brvah_emptyClickListener"})
        public static void onEmptyView(RecyclerView recyclerView, ObservableInt emptyResId, View.OnClickListener clickListener) {
            CSLog.Print("加载空布局调用");
            RecyclerView.Adapter adapter = recyclerView.getAdapter();
            if (adapter instanceof BaseQuickAdapter) {
                if (emptyResId != null) {
                    CSLog.Print("进入加载空布局");
                    ((BaseQuickAdapter) adapter).setEmptyView(emptyResId.get(), (ViewGroup) recyclerView.getParent());
                }
                if (clickListener != null && ((BaseQuickAdapter) adapter).getEmptyView() != null) {
                    CSLog.Print("进入加载空布局监听事件");
                    ((BaseQuickAdapter) adapter).getEmptyView().setOnClickListener(clickListener);
                }
     
            }
        }
    

    上面这些是CSBrvahBindingAdapter中,databinding绑定的代码。其实归根到底,还是调用了BRVAH的方法。

    哇,又写了这么多了,那再起一页吧。
    BRVAH的BaseRecyclerViewAdapterHelper与MVVM模式优雅结合(其一)
    BRVAH的BaseRecyclerViewAdapterHelper与MVVM模式优雅结合(其三)

    相关文章

      网友评论

        本文标题:BRVAH的BaseRecyclerViewAdapterHel

        本文链接:https://www.haomeiwen.com/subject/kdpbactx.html