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. 【起航计划 021】2015 起航计划 Android APIDemo的魔鬼步伐 20 App->Intents createChooser

    Intents 这个例子的代码非常简单: public void onGetMusic(View view) { Intent intent = new Intent(Intent.ACTION_GE ...

  2. u-boot分析(四)---设置异常向量表|设置SVC模式

    u-boot分析(四) 通过前三篇的分析,我们对u-boot已经有了整体的认识和掌握,但是我们仍然对于其部分硬件是如何初始化的不太清楚,所以接下来几篇博文我将会对我们在http://www.cnblo ...

  3. TeamViewer安装使用

    1.下载安装包 官网下载最新安装包 2.安装步骤 3.连接 输入密码即可控制伙伴电脑.

  4. SharePoint 计时器作业

    本文将介绍 SharePoint 2010 的默认计时器作业,即我们通常说的Timer服务.计时器作业在 SharePoint Server 的特定 Windows 服务中运行.计时器作业还是执行定时 ...

  5. NFS笔记(一)NFS服务器工作原理及详细配置

    一.NFS工作原理 1.什么是NFS服务器 NFS就是Network File System的缩写,它最大的功能就是可以通过网络,让不同的机器.不同的操作系统可以共享彼此的文件. NFS服务器可以让P ...

  6. 如何将Twitter的内容导入到SAP CRM和C4C

    Twitter的内容导入SAP CRM Interaction Center呼叫中心 具体步骤查看我的博客Twitter(also Facebook) is official integrated i ...

  7. 剑指offer39 平衡二叉树

    剑指上用了指针传递,这里用的引用传递 class Solution { public: bool IsBalanced_Solution(TreeNode* pRoot) { ; return IsB ...

  8. python剑指offer数组中出现次数超过一半的数字

    题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...

  9. sz 命令

    sz命令 下载文件命令 sz  文件名

  10. pyinstaller打包后的exe退出时,类中的__del__不执行问题

    关于pyinstaller打包后的exe退出时,类中的__del__不执行问题,完善中