摘要:在上一篇中对MVP模式进行了封装,然后通过封装之后的类,实现了一个网络请求,但是请求到网络数据之后,就直接展示到了 View 层,并没有其他的操作,然而我们在开发过程中, 经常会用到分页加载,一般在滑动控件向上滚动,加载更多事件触发是调用,并且这个过程设计到两个参数,一个是 PageIndex :页码;一个是 PageSize 一页数据的大小, 分页加载就是通过在某一具体事件触发时,调用修改这两个或者一个参数,重新请求网络,从而拿到下一页的数据,这边文章还是基于MVP模式,对分页数据的请求进行封装。
presenter 层作为 MVP 模式的桥梁, 那就先从这一层开始说起吧。
Presenter
上一篇中对 Presenter 层的公共方法进行了抽取并且封装成了一个接口 IBasePresenter ,那么现在我们需要实现分页加载还有刷新的功能,那么在 IBasePresenter 接口的基础之上,在对其封装一个接口 IBasePeginationPresenter:
|
也是一个泛型的接口,增加的三个方法 :
-
refresh(Param param)在View层调用,用于通知Model层刷新数据 -
loadingNext()在View层调用,用于通知Model层加载下一页数据 -
hasMoreData()在Model层请求网络数据前调用做判断,是否还有下一页数据
有了针对分页刷新的接口之后,还需要有一个实现它的基类:
|
- 在类申明时,可以看到
Param extends BasePeginationParam,这里的BasePeginationParam主要是封装了摘要中提到的PageIndex和PageSize两个参数,以及他们的Getter Seeter方法。 - 重点看
IBasePeginationPresenter中新增加的三个方法,refresh(Param param)会重新调用一次requestServer(Param param)(此方法在上一篇也提过了,就是通知Model层获取数据); -
loadingNext(),加载下一页数据的方法,就是将参数中的PageIndex + 1之后,重新调用requestServer(Param param)方法。此处只改变了页码,如果需要改变请求数据的条数,也是相应的在loadingNext()中修改PageSize的值。 -
hasMoreData(),这里返回抽象方法serverhaveMoreData(),这个方法是在子类中实现的,子类解析了数据之后,判断服务器是否还有数据返回。
然后有需要实现分页功能的 Presenter 就可以直接继承 BasePaginationPresenter 。
Model 层
由于 Model 层的职责比较单一,就是向数据源请求数据,并且返回给 Presenter 层,所以此处不需要额外封装接口或者是基类,只需要重新实现上一篇中提到的 IBaseModel 接口即可。
View 层
此处和请求一次数据相比较, View 层就是需要在两个事件触发的时候,重新设置参数通知 Presenter 去请求数据,然后再展示出来。这两个事件分别是:上拉到底时加载更多、下拉时刷新数据(当然可以别的)。
针对上一小节中封装类的具体实现
View 层的具体实现
主要是展示电视剧的主要信息,那么需要提供一个接口方法,给 Presenter 层调用,展示处理好的 JavaBean:
|
此处的 VideoInfo 是一个JavaBean,对应的就是电视剧信息的实体类。
|
之前映射数据需要保证字段名和
Json数据的字段名一致,其实本来把这个类的字段名改得一致就行啦,但是服务器端返回的数据字段,很多都是以“_”进行连接,而不是使用驼峰命名法则,这个时候Gson的@SerializedName注解就派上用场了,注解中用服务器端返回值字段,成员变量仍然使用驼峰命名法。但是上个周末安装了最近
Alibaba 10 月 14 日推出的Coding Guidelines插件,发现代码中很多不规范的地方,并且人家规定了成员变量就必须要使用驼峰命名!所以我决定要按照这个插件的规范来写代码了,虽然现在进不了大厂,但是先熟悉大厂的代码规范也是好事,哈哈~ 咳咳,按照大厂的代码规范,成员变量的命名必须使用驼峰命名法!这个插件是真心好用,比如对类名要
javadoc注释 参数、返回值、异常说明、此方法做什么事情、实现什么功能(领域模型相关命名除外,比如:DO、BO、DAO),并且是全中文的!直接在AS的Inspection Results窗口中显示,这IDE内置功能啥时候讲过中文反馈结果的?广告时间结束,言归正传!
这个 Activity 实现了 ISohuSerials 接口,布局文件和上一篇一样,只是把 ListView 换成了自定义的 PullLoadRecyclerView 了,这个RecycyclerView 支持上拉加载更多和下拉刷新, 这里不展开说了。
|
在上面代码中可以看到:
- 在
PullLoadRecycler.OnPullLoadMoreListenre的onRefresh()回调方法中,核心代码就是这一行mAlbumPresenter.refresh(mParam);,通知Presenter层去刷新数据, 至于Presenter层如何刷新。。 关我View层 X 事~ - 在
PullLoadRecycler.OnPullLoadMoreListenre的onLoadMore()回调方法中,也是直接调用mAlbumPresenter.loadingNext()。
下面说说 Presenter 层的代码
Presenter 层的具体实现
|
- 首先是要继承之前编写的
BasePaginationPresenter类,泛型参数BasePaginationParam可以根据实际需求进行拓展,基本使用在前面已经介绍过,此处不做赘述。 -
Album是搜狐视频电视剧频道返回数据的实体类,上面提到的VideoInfo包含在Album里面,因为现在只需要展示VideoInfo里的信息, 所以在serverRespomse方法里,有一个转换mBaseListView.showAlbumMainInfo(album.getData().getVideos()); - 实现父类
BasePaginationPresenter中的抽象方法serverHaveMoreData(),思路就是 当前页面数 * 每一页的数据量,然后和 数据总量 比较大小。
Model 层的具体实现
|
Model 层的实现还是跟之前的一样,直接实现 IBaseModel 接口即可。
- 在
17行可以看到,mPaginationPresenter.hasMoreData(),这个就是对服务器点是否还有数据可以返回的判断,如果这里返回false那么就不回去进行网络请求,然后在22行打印个Log提醒。 - 在看看
49行的getVaildUrl方法,这个方法主要就是把传进来的param参数拼接进url中,形成有效的,可以请求到数据的Url。
效果图
Item 就展示了一下电视剧的 主演、名字、导演、集数、更新时间的信息。
小结
通过上面的封装和例子,起码证明了这一套封装能够跑的通了,以后如果还有关于分页请求的需求,可以直接继承上面的基类来实现,无非就是修改param 和 Data 两个泛型的参数。
- 前者是请求
url的参数,根据具体的业务需求,封装BasePaginationParam的子类即可。 - 后者是服务器端返回数据的实体类,也是根据数据的结构来封装的,在
Android Studio中有Gson Formatter这个插件,封装JavaBean插件也轻松很多,在结合上面提到的Gson注解,全套了。
下一篇准备封装一下
OkHttp,然后将封装之后的OkHttp整合到当前框架中,当然了,还是以分页接在为例