• TouTiao开源项目 分析笔记8 图解分析数据加载方式


    1.整体构架

    1.1.以一个段子页面为例,列出用到的主要的类,以图片的方式展示。

    1.2.基础类

      这里最基础的接口有:   IBaseView<T>==>定义了5个方法。

      然后最基础的碎片是:BaseFragment<T extends IBasePresenter>==>3个抽象方法。

      然后继承BaseFragment的抽象类:LazyLoadFragment<T extends IBasePresenter>==>1个抽象类

      然后继承LazyLoadFragment的抽象类:BaseListFragment<T extends IBasePrestener>==>最复杂的类

      然后BaseListFragment实现的接口:IBaseListView<T> ==>加上IBaseView<T>总共有7个方法。

      然后定义最基本的处理器:IBasePresenter==>这里面只有两个方法,一个刷新,一个显示网络错误。

    1.3.具体实现类

      这里以一个JokeContentView片段为例,加载一个段子的页面。

      

      这个JokeContentView继承了BaseListFragment<IJokeContent.Presenter>

      这个IJokeContent接口中有两个大接口。一个是View接口==>1+7=8个方法。==>视图显示

      另外一个是Presenter接口==>2+4=6个方法。==>请求数据


    2.具体接口分析

    2.1.IBaseView<T>接口

      最基础的视图接口类5个方法。

    • void onShowLoading()==>显示加载动画。
    • void onHideLoading()==>隐藏加载。
    • void onShowNetError()==>显示网络错误。
    • void setPresenter(T)==>设置处理器。
    • <T> LifecycleTransformer<T> bindToLife()==>绑定生命周期。 

    2.2.IBaseListView<T> 继承IBaseView<T>

       加上自己的两个,总共有7个方法。

    • void onShowLoading()==>显示加载动画。
    • void onHideLoading()==>隐藏加载。
    • void onShowNetError()==>显示网络错误。
    • void setPresenter(T)==>设置处理器。
    • <T> LifecycleTransformer<T> bindToLife()==>绑定生命周期。
    • void onSetAdapter<List<?> list>==>设置适配器。
    • void onShowNoMore()==>加载完毕。 

    2.3.IBasePresenter==>最基础的处理器

    • doRefresh()==>处理刷新数据。
    • doShowNetError()==>处理网络错误。  

     

    2.4.IJokeContent==>段子接口分析

      2.4.1.interface View==>显示视图的接口。   

    1.onShowLoading==>显示加载动画
    2.onHideLoading==>隐藏加载
    3.onShowNetError==>显示网络错误
    4.setPresenter==>和 IJokeContent的Presenter有关
    5.bindToLife==>返回LifecycleTransformer<T>
    6.onSetAdapter(List<?> list)==>设置适配器
    7.onShowNomore==>加载完毕
    8.onLoadData()==>请求数据============新增的

      2.4.2.interface Presenter==>初始数据的接口。

    1.void doRefresh()==>处理刷新数据。
    2.void doShowNetError()==>处理显示网络错误。
    3.void doLoadData()==>处理请求数据。
    4.void doLoadMoreData()==>请求更多数据。
    5.void doSetAdapter()==>设置适配器。
    6.void doShowNoMore()==>没有更多了。


    3.具体类分析

    3.1.最基础的类应该就是BaseFragment<T extends IBasePresenter>

      这里面定义了一个处理器。

      实现了IBaseView<T>接口的一个方法。==>bindToLife()

      在onCreate中调用了IBaseView<T>接口的一个方法。==>setPresenter(presenter)

      所以还有4个接口这里没有提到。

    IBaseView<T>还有三个接口这里没有提到:
    1.onShowLoading()==>显示加载动画
    2.onHideLoading()==>隐藏加载动画
    3.onShowNetError()==>显示网络错误
    4.setPresenter(presenter)==>设置适配器
        调用了,但是没有具体实现。

      这里面又申请了3个抽象函数。 

    3个抽象方法。
    1.attachLayoutId()==>绑定布局文件
    2.initView(view)==>初始化视图控件
    3.initData()==>初始化数据

    3.2. LazyLoadFragment<T extends IBasePresenter>==>懒加载中介碎片类

      这里有一个函数比fragment的onCreate还要先执行==>setUserVisibleHint

      可以参考一下这篇文章了解setUserVisibleHint的作用。

      得到的结论就是:

       

    先执行setUserVisibleHint==>在所有fragment生命周期之前,执行不可见即isVisibleToUser为false
    然后执行准备填充数据。直到视图加载完毕+对用户可见+数据初始化完毕才会执行抽象函数fetchData()
    直到onActivityCreated刚好执行,isViewInitiated为真,
    然后对用户可见,然后数据还没有初始化,那么就会执行fetchData抽象函数了。

      然后在LazyLoadFragment中又增加了一个抽象方法。

      所以现在总共有4个抽象方法还未实现:

    • onShowLoading()==>显示加载动画。
    • onHideLoading()==>隐藏加载动画。
    • onShowNetError()==>显示网络错误。
    • fetchData()==>在onCreateView的最后执行的一个填充数据的抽象函数。  

    3.3.高级抽象类BaseListFragment<T extends IBasePresenter>

      3.3.1.首先实现BaseFragment中的抽象函数。

    实现了BaseFragment中的抽象函数attachLayoutId==>R.layout.fragment_list.
    实现了BaseFragment中的抽象函数initView==>得到recyclerView和swipeRefreshLayout+注册监听

      3.3.2.然后实现了LazyLoadFragment中的抽象函数fetchData

    实现了LazyLoadFragment中的抽象方函数
    fetchData==>用了一个RxBus(和Observable有关系,用了RxJava框架)
    在observable.suscribe中执行adapter的刷新。

      3.3.3.然后实现IBaseListView接口方法

        实现了4个  

    实现了BaseFragment中的IBaseView接口onShowLoading==>调用了swipeRefreshLayout的setRefreshing(1)
    实现了BaseFragment中的IBaseView接口onHideLoading==>调用了swipeRefreshLayout的setRefreshing(0)
    实现了BaseFragment中的IBaseView接口onShowNetError==>Toast了一下,然后用异步执行了adapter的刷新
    加载完毕==>这个是IBaseListView继承IBaseView新增的两个方法中的一个
    2.onShowNoMore==>异步执行了判断原来是否有数据,然后在加一个尾巴在数据后面,然后再执行adapter的刷新。

        还有两个等待子类实现。一个是设置适配器,一个是设置处理器。

    IBaseListView<T>继承IBaseView因此多了两个待实现的接口函数==>设置适配器
    1.onSetAdapter==>这里没有具体实现,可能在子类中实现了。
    没有实现IBaseView接口中的
    setPresenter==>这里没有具体实现

      3.3.4.然后实现SwipeRefreshLayout刷新。

    实现SwipeRefreshLayout刷新。
    复写了方法onRresh()
    这里调用了BaseFragment中的
    presenter中的一个doRefresh方法。其实定义在JokeContentPresenter类中。

      

      3.3.5.然后实现生命周期函数。

    执行onResume
    这里设置下拉刷新按钮的颜色。
    执行onDestroy
    这里将RxBus中BaseListFragment反注册,需要传入TAG+observable。

      3.3.6.最后还有一个未实现BaseFragment中的抽象函数。

    未实现BaseFragment中的抽象函数
    initData()==>这个在具体碎片中执行。


    4.实际应用类

    4.1.实际应用视图类==>JokeContentView

      4.1.1.实现抽象方法。==>设置适配器。

    实现BaseListFragment未实现的IBaseView接口方法。
    1.onSetAdapter==>调用了自定义类DiffCallback注册adapter类型。用到MultiTypeAdapter的第三方库。

      4.1.2.实现抽象方法。==>设置处理器。

    实现BaseListFragment未实现的IBaseView接口方法。
    2.setPresenter==>这里设置了一个JokeContentPresenter类型为处理器,所以每个类型adapter+presenter都不一样的。

      4.1.3.实现抽象方法。==>initData()

    实现BaseListFragment未实现的BaseFragment抽象方法
    1.initData()==>这里是一个空函数,如果有其他初始化数据的必要,在这里面加一些额外信息即可。

      4.1.4.实现接口方法。==>onLoadData()

    实现IJokeContent.View接口的
    onLoadData方法
    先执行BaseListFragment中的onshowLoading函数,然后调用处理器的presenter.doLoadData()

      4.1.5.重写fetchData函数。==>懒加载里面最重要的一个函数。

    重写LazyLoadFragment中的fetchData
    在BaseListFragment有具体的实现和observable和RxBus产生联系。
    然后在JokeContentView中执行了一个
    onLoadData函数。

      4.1.6.重写initView(view)。==>BaseListFragment的已经执行过的initView(view)

    重写BaseListFragment的BaseFragment的抽象方法,已经在BaseList执行过。
    2.initView(view)==>先执行super.initView(view),然后新建一个adapter,调用了Register自定义类注册类型。
    然后将注册器加入recycleView中。然后执行滑动监听==>自己写了一个监听器onLoadMoreListener来加载更多,
    调用presenter.doLoadMoreData()方法。

    4.2.实际应用处理器。

      4.2.1.总共6个接口函数。

    总共6个接口函数
    定义在IJokeContent.Presenter有4个
    1.doLoadData()==>请求数据
    2.doLoadMoreData()==>请求更多数据
    3.doSetAdapter()==>设置适配器
    4.doShowNoMore()==>没有更多了
    +IBasePresenter有2个
    5.doRefresh()==>刷新数据
    6.doShowNetError()==>显示网络错误

      4.2.2.第一个接口函数实现。

    1.doLoadData()
        这里和自定义缓存类RetrofitFactory有关。这里调用今日头条的API。
      通过ToutiaoUtil爬虫爬到了As和Cp。将数据放到groupList中,然后调用处理器的   doSetAdapter或者doShowNoMore()。
     @Override
        public void doLoadData(){
            if(NetWorkUtil.isNetworkConnected(InitApp.AppContext)) {
                //这里需要更改!!!
                Map<String, String> map = ToutiaoUtil.getAsCp();
    
                RetrofitFactory.getRetrofit().create(IJokeApi.class).getJokeContent(time, map.get(Constant.AS), map.get(Constant.CP))
                        .subscribeOn(Schedulers.io())
                        .map(new Function<JokeContentBean, List<JokeContentBean.DataBean.GroupBean>>() {
                            @Override
                            public List<JokeContentBean.DataBean.GroupBean> apply(@NonNull JokeContentBean jokeContentBean) throws Exception {
                                List<JokeContentBean.DataBean> data = jokeContentBean.getData();
                                for (JokeContentBean.DataBean dataBean : data) {
                                    groupList.add(dataBean.getGroup());
                                }
                                time = jokeContentBean.getNext().getMax_behot_tim() + "";
                                return groupList;
                            }
                        })
                        .compose(view.<List<JokeContentBean.DataBean.GroupBean>>bindToLife())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Consumer<List<JokeContentBean.DataBean.GroupBean>>() {
                            @Override
                            public void accept(@NonNull List<JokeContentBean.DataBean.GroupBean> groupBeen) throws Exception {
                                if (groupBeen.size() > 0) {
                                    doSetAdapter();
                                } else {
                                    doShowNoMore();
                                }
                            }
                        }, ErrorAction.error());
            }else{
                doShowNetError();
            }
        }

      4.2.3.第二个接口函数实现。

    2.doLoadMoreData()
        请求更多的数据。
         执行处理器中的doLoadData()函数。
     @Override
        public void doLoadMoreData(){
            doLoadData();
        }

      4.2.4.第三个接口函数实现。

    3.doSetAdapter()
        设置适配器
         执行接口IJokeContent.View中的onSetAdapter(groupList)+onHideLoading()
    @Override
        public void doSetAdapter(){
            view.onSetAdapter(groupList);
            view.onHideLoading();
        }

      4.2.5.第四个接口函数实现。

    4.doShowNoMore()
        没有更多了
         这里执行接口IJokeContent.View中的
    onHideLoading()+onShowNoMore()
      @Override
        public void doRefresh(){
            if(NetWorkUtil.isNetworkConnected(InitApp.AppContext)) {
               if(groupList.size()!=0){
                groupList.clear();
               }
                view.onShowLoading();
                doLoadData();
    
            }else{
                doShowNetError();
            }
        }

      4.2.6.第五个接口函数实现。

    5.doRefresh()
        刷新数据
        先clear 然后执行IJokeContent.View接口的
    onShowLoading
    然后执行处理器的
    doLoadData方法。
     @Override
        public void doShowNetError(){
            view.onHideLoading();
            view.onShowNetError();
        }

      4.2.7.第六个接口函数实现。

    6.doShowNetError()
        显示网络错误
        执行IJokeContent.View接口的onHideLoading和onShowNetError方法。
     @Override
        public void doShowNoMore(){
            view.onHideLoading();
            view.onShowNoMore();
        }


    既然选择了,便不顾风雨兼程。Just follow yourself.
  • 相关阅读:
    遮罩层点击空白退出代码
    不同浏览器的margin值与padding值
    让div自适应浏览器窗口居中显示
    导航相关(下方导航指示条居中)
    CSS相邻兄弟选择器
    使用font-size:0去掉inline-block元素之间的空隙
    box-sizing属性
    常见浏览器兼容性问题
    秋季编程总结
    POJ 1193 内存分配
  • 原文地址:https://www.cnblogs.com/Jason-Jan/p/7998770.html
Copyright © 2020-2023  润新知