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==>显示视图的接口。   

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

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

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

3.具体类分析

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

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

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

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

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

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

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

3个抽象方法。
.attachLayoutId()==>绑定布局文件
.initView(view)==>初始化视图控件
.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()
实现了BaseFragment中的IBaseView接口onHideLoading==>调用了swipeRefreshLayout的setRefreshing()
实现了BaseFragment中的IBaseView接口onShowNetError==>Toast了一下,然后用异步执行了adapter的刷新
加载完毕==>这个是IBaseListView继承IBaseView新增的两个方法中的一个
.onShowNoMore==>异步执行了判断原来是否有数据,然后在加一个尾巴在数据后面,然后再执行adapter的刷新。

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

IBaseListView<T>继承IBaseView因此多了两个待实现的接口函数==>设置适配器
.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接口方法。
.onSetAdapter==>调用了自定义类DiffCallback注册adapter类型。用到MultiTypeAdapter的第三方库。

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

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

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

实现BaseListFragment未实现的BaseFragment抽象方法
.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执行过。
.initView(view)==>先执行super.initView(view),然后新建一个adapter,调用了Register自定义类注册类型。
然后将注册器加入recycleView中。然后执行滑动监听==>自己写了一个监听器onLoadMoreListener来加载更多,
调用presenter.doLoadMoreData()方法。

4.2.实际应用处理器。

  4.2.1.总共6个接口函数。

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

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

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

TouTiao开源项目 分析笔记8 图解分析数据加载方式的更多相关文章

  1. TouTiao开源项目 分析笔记7 加载数据的过程

    1.以新闻页中的段子数据显示为例 1.1.首先执行InitApp==>SplashActivity. 因为在AndroidManifest.xml中定义了一个<intent-filter& ...

  2. TouTiao开源项目 分析笔记6

    1.NewsChannelBean简单类笔记 1.1.Comparable接口的实现和使用 参考文章:Comparable接口的实现和使用. 因为NewsChannelBean实现了Comparabl ...

  3. TouTiao开源项目 分析笔记2

    1.Constant常量定义类 1.1.源代码 public class Constant { public static final String USER_AGENT_MOBILE = " ...

  4. TouTiao开源项目 分析笔记15 新闻详情之两种类型的实现

    1.预览效果 1.1.首先看一下需要实现的效果. 第一种,文字类型新闻. 第二种,图片类型新闻. 1.2.在NewsArticleTextViewBinder中设置了点击事件 RxView.click ...

  5. TouTiao开源项目 分析笔记10 实现通用普通文章片段页面

    1.RxJava的Observable数据操作符总结 1.1.Map操作符 Map操作符对原始Observable发射的没一项数据应用一个你选择的函数, 然后返回一个发射这些结果的Observable ...

  6. TouTiao开源项目 分析笔记18 视频详情页面

    1.效果预览 1.1.需要做到的真实效果 1.2.触发的点击事件 在MediaArticleVideoViewBinder的每一个item点击事件中: VideoContentActivity.lau ...

  7. TouTiao开源项目 分析笔记17 新闻媒体专栏

    1.效果预览 1.1.要实现的效果 1.2.如何调转到新闻媒体专栏 点击右上角的用户图标. 在新闻详情页面的Fragment的菜单点击事件中触发. case R.id.action_open_medi ...

  8. TouTiao开源项目 分析笔记16 新闻评论

    1.要达到的效果 1.1.主要效果图 点击了标题栏的消息图标后,然后会跳转到评论详情的页面. 1.2.触发的点击事件 在新闻详情的片段中的菜单点击事件中 设置上方标题栏的消息标的监听事件 case R ...

  9. TouTiao开源项目 分析笔记14 段子评论

    1.段子页面详情 1.1.先看看预览界面吧 左边的页面已经实现了,现在的目的就是要实现点击左侧的每一个item 然后跳转到右边相应的段子详情页面. 1.2.首先肯定有右侧这个活动==>JokeC ...

随机推荐

  1. iRecognizer号码扫描开发实录

    iRecognizer——这是一款可以帮助你快速扫描获得印刷体数字的软件 现已上架 腾讯应用宝,酷安 提供的功能:扫一扫(相册或当场扫描),获得电话号码,之后就可以拨打或者发送短信,自动复制到剪贴板, ...

  2. MySQL入门很简单: 5 索引

    1. 索引的含义和特点 索引:创建在表上,是对数据库表中一列或多列的值进行排序的一种结构. 存储类型: B性树(BTREE)索引和哈希(HASH)索引: InnoDB和MyISAM支持BTREE索引, ...

  3. SAP成都研究院飞机哥: SAP C4C中国本地化之微信聊天机器人的集成

    今天的文章仍然来自Jerry的老同事,SAP成都研究院的张航(Zhang Harry).关于他的背景介绍,请参考张航之前的文章:SAP成都研究院飞机哥:程序猿和飞机的不解之缘.下面是他的正文. 大家好 ...

  4. robotframework实战一

    1.环境 1.Robotframework 安装环境,见以下帖子,只要保证python安装成功,安装了python的pip,就可以使用pip一路安装下去了.以下帖子也有基础的操作,帖子路径 http: ...

  5. bzoj4943 [Noi2017]蚯蚓排队

    题面:http://www.lydsy.com/JudgeOnline/upload/Noi2017D1.pdf 正解:字符串$hash$. 我在考场上写了个$map$的$hash$被卡成$40$分, ...

  6. 【CCPC-Wannafly Winter Camp Day4 (Div1) G】置置置换(动态规划)

    点此看题面 大致题意: 求出有多少个长度为\(n\)的排列满足对于奇数位\(a_{i-1}<a_i\),对于偶数位\(a_{i-1}>a_i\). 考虑打表? 考虑每次只有一个数\(n\) ...

  7. centos下yum安装mysql5.6后,无法启动 MySQL Daemon failed to start

    如果是全新安装应该就不会出现这个问题,升级安装的话,要运行 mysql_upgrade ,但是启动MYSQL就报错MySQL Daemon failed to start 如此就没办法运行mysql_ ...

  8. 1012: A MST Problem

    1012: A MST Problem 时间限制: 1 Sec  内存限制: 32 MB提交: 63  解决: 33[提交][状态][讨论版][命题人:外部导入] 题目描述 It is just a ...

  9. 2017.9.30 Java中引用类型变量的创建及使用&循环的高级

    今日内容介绍 1.引用类型变量的创建及使用 2.流程控制语句之选择语句 3.流程控制语句之循环语句 4.循环高级 ###01创建引用类型变量公式     * A: 创建引用类型变量公式         ...

  10. CentOS7 设置开机自启

    [root@master-1 ~]# systemctl enable mariadb ln -s '/usr/lib/systemd/system/mariadb.service' '/etc/sy ...