孟老板 BaseAdapter封装(四) PageHelper
- BaseAdapter封装(一) 简单封装
- BaseAdapter封装(二) Header,footer
- BaseAdapter封装(三) 空数据占位图
- BaseAdapter封装(四) PageHelper
- ListAdapter系列
- Paging3 系列
1.分页帮助类
前言:
分页列表, 可谓是家常便饭. 完成分页逻辑,需要的模板代码比较多. 应将这些代码归纳封装,统一处理;
1.1 模板代码有哪些:
1.页码, 数据
2.加载更多功能的控制 (最后一页时关闭加载逻辑, 刷新时重置页码, 重新启动加载逻辑)
3.网络请求,
4.更甚至, Adapter初始化. RecycleView初始化, 空占位图情况下切换显示没有更多View等
1.2 helper 执行过程:
1.初始化
2.获取请求参数, 请求地址, 发起网络请求; 解析响应
3.如果当前不是第一页, 则追加数据; 如果当前最后一页, 则显示没有更多
4.如果第一页, 判断启动加载更多的监听; (空占位等)
博主使用的 loadmorewrapper 这个库.
implementation 'com.github.nukc:loadmorewrapper:1.8.3'
博主并没有把这个类维护的比较完善, 这年头也只有老程序员才会在Activity中发请求吧; 这个类只当做是一次对模板代码的封装吧; 有兴趣的小伙伴可以自行控制执行逻辑;
由于后台给的数据形式比较乱, 网络请求的返回值用json接收;
MVP 版本的话, 需要分开单独处理 view, presenter 层; 也可以用继承方式抽调模板代码;
好, 我们上代码 (用 kotlin 写的)
注意: 博主 executePOST() 方法的第一个参数是个 tag; 页面关闭时,会取消网络请求; 防止内存泄漏
class MyPageHelper<T, A : BaseAdapter<T>>( val mAdapter: A, private val mRecycle: RecyclerView, private val mView: PagingView) { //页码参数 private val pageInit = 1 private var page: Int = 1 private var pageSize: Int = 10 private var maxPage: Int = 1 private var mWrapper: LoadMoreWrapper? = null private var mEnabled: LoadMoreAdapter.Enabled? = null private lateinit var mData: MutableList<T> /** * 初始化就执行加载; 也可以用load()方法延迟加载; */ init { refresh() } // fun load(){ // refresh() // } /** * 刷新重置数据 */ fun refresh(){ page = pageInit requestData() } private fun requestData(){ val map = ArrayMap<String,Any>() map["page"] = page map["pageSize"] = pageSize val url = mView.prepareMap(map) OkGoUtils.executePOST(mView, url, map, object : OkGoCallBack { override fun onSuccess(jsonObject: JSONObject, msg: String, params: Map<String, Any>) { val jo = jsonObject.getJSONObject("data") maxPage = if(jo.has("totalPage")) jo.getInt("totalPage") else 1 val data = mView.analysisData(jo) updateData(data as MutableList<T>) } override fun onFailure(msg: String) { ToastUtil.toastShortMessage(msg) } }) } /** * 更新数据集合 */ private fun updateData(data: MutableList<T>) { //根据是不是第一页, 来处理数据; if (page <= pageInit) { disposeFirstPage(data) } else { if(data.isNotEmpty()) { mAdapter.data.addAll(data) mAdapter.notifyDataSetChanged() } } /** * 如果当前页码值, 已经超过总页码数, 则没有更多 */ noMoreData(page >= maxPage) } /** * 第一页数据处理逻辑; */ private fun disposeFirstPage(data: MutableList<T>) { //第一个数据, 必定重新赋值; mData = data //mAdapter 中 setData 时自动 notifyDataSetChanged(); mAdapter.data = mData if(mWrapper == null){ //只有当 mWrapper 为null时 才初始化 mWrapper = LoadMoreWrapper.with(mAdapter).apply { setShowNoMoreEnabled(true) // enable show NoMoreView,default false setListener { enabled: LoadMoreAdapter.Enabled -> mEnabled = enabled if (page >= maxPage) { noMoreData(true) } else { page++ requestData() } }.into(mRecycle) } }else{ //是否显示没有更多视图; 当显示空数据占位图时,才可能置为false; mWrapper?.setShowNoMoreEnabled(true) } } /** * 控制加载更多功能; */ private fun noMoreData(none: Boolean) { mEnabled?.let { if (none) { it.loadMoreEnabled = false //停止加载更多逻辑 //更新指定位置,Adapter一般有得到数据和设置数据; 为什么没有 -1? 没有更多页面也算一条 mAdapter.notifyItemChanged(mAdapter.itemCount) } else { it.loadMoreEnabled = true //启动加载更多逻辑 } } } interface PagingView{ /** * 维护请求数据 */ fun prepareMap(map: ArrayMap<String, Any>) : String /** * format Request响应; 解析成 Adapter 所需数据集合 */ fun analysisData(jo: JSONObject): MutableList<out Any> // fun loading() // fun hideLoading() }
使用:
1.activity, fragment 需要实现 PagingView; 提供请求连接,及请求参数; 以及解析数据
2.初始化, RecycleView Adapter, 并启动实例化 MyPageHelper
initRecycle(){
//... 初始化 Adapter, RecycleView, 并实例化 MyPageHelper
mHelper = MyPageHelper<>(mAdapter, rv_recycle, this)
}
override fun prepareMap(map: ArrayMap<String, Any>): String { map["cycleId"] = cycleId return APIConfig.ARTICLE_LIST_AUDIT } override fun analysisData(jo: JSONObject): MutableList<out Any> { maxNum = jo.getInt("totalNum") return GsonUtils.toList(jo.getString("newsList"), NewsEntity::class.java) }