孟老板 ListAdapter封装, 告别Adapter代码 (四)
2024-09-08 11:31:57
- BaseAdapter系列
- ListAdapter封装, 告别Adapter代码 (一)
- ListAdapter封装, 告别Adapter代码 (二)
- ListAdapter封装, 告别Adapter代码 (三)
- ListAdapter封装, 告别Adapter代码 (四)
- Paging3 系列
ListAdapter封装 (四) - 分页封装;
前言:
这是ListAdapter最后一篇了; 简单封装一下分页逻辑; 由于框架五花八门(网络请求, 下拉刷新, 加载更多等),这篇只做参照即可;
分析:
ViewModel 需要处理: 页码, 请求解析数据, 发送加载更多状态, 发送下拉刷新状态等;
View 需要处理: 初始化Adapter, RecycleView. 绑定加载更多控件, 监听下拉及加载更多状态等;
本篇用到的库:
//loadmore
implementation 'com.github.nukc:loadmorewrapper:1.8.3' //retrofit 2.9 系列
implementation "com.squareup.retrofit2:retrofit:2.9.0" //viewmodel
implementation "androidx.lifecycle:lifecycle-viewmodel:2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0"
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
1.BasePageModel;
它是分页 ViewModel 的基类. 使用 retrofit 拉取数据;
abstract class BasePageModel<T: BaseItem> (application: Application) : AndroidViewModel(application){
private var pageInit = 1
private var page = pageInit
private var pageSize = 10
private var maxPage: Int = 1 /**
* 下拉刷新状态,
*/
var refreshEnabled: MutableLiveData<Boolean> = MutableLiveData(false) /**
* 加载更多状态
*/
var loadEnabled: MutableLiveData<Boolean> = MutableLiveData(true) /**
* 列表数据
*/
var listData: MutableLiveData<MutableList<T>> = MutableLiveData(mutableListOf()) fun loadData(param: ArrayMap<String, Any>){
param["page"] = page
param["pageSize"] = pageSize //发起网络请求.
retrofit<JsonObject>(viewModelScope) {
onSuccess {
disposeResp(it)
}
onFailed { msg, _ ->
Toast.makeText(getApplication(), msg, Toast.LENGTH_SHORT).show()
}
onComplete {
refreshEnabled.value = false
} api = getResp(ApiManager.INSTANCE.getJsonBody(param))
}
} /**
* 处理响应;
* 1.解析响应数据; 2.获取总页码数; 3.拼接数据;
* 4.页码++ 5.判断loadMore Enabled 6.取消下拉刷新状态
*/
private fun disposeResp(resp: BaseResp<JsonObject?>){
val list = analysisData(resp.data) ?: mutableListOf()
maxPage = resp.data?.asJsonObject?.get("totalPage")?.asInt ?: 1 if (page == pageInit) {
listData.value = list
} else {
val data = listData.value
data?.addAll(list)
listData.value = data
}
page++ if (page > maxPage) {
switchEnabled(false)
} else {
//数据够,则继续加载; 数据不够了,则关闭加载
switchEnabled(list.size >= pageSize)
}
} /**
* 切换 loadMore Enabled;
*/
private fun switchEnabled(boolean: Boolean){
if(boolean != loadEnabled.value){
loadEnabled.value = boolean
}
} /**
* 重新加载数据;
*/
fun reload(){
page = pageInit
listData.value = mutableListOf()
switchEnabled(true)
} /**
* 处理数据, 因服务器响应数据不规范, 只能用Json接收;
* 可以省去 - 当响应数据可以直接解析为 实体集合时,
*/
abstract fun analysisData(jo: JsonObject?): MutableList<T>? /**
* retrofit API
*/
abstract suspend fun getResp(rBody: RequestBody): BaseResp<JsonObject?>
}
2. ViewModel
它继承 BasePageModel;
class CheckModel(application: Application) : BasePageModel<CheckEntity>(application) { override fun analysisData(jo: JsonObject?): MutableList<CheckEntity>? {
val str: String? = jo?.getAsJsonArray("newsList")?.toString()
//将String 解析为 实体集合
return str?.toBeanList()
} override suspend fun getResp(rBody: RequestBody): BaseResp<JsonObject?> {
return ApiManager.INSTANCE.mApi.getDynamicList(rBody)
} }
3. MyPageHelper
使用 loadmorewrapper 库 加载更多; 监听数据, 监听状态都写在这个类里
class MyPageHelper(
adapter: BaseAdapter<out BaseItem>,
private val mRecycle: RecyclerView,
private val pageModel: BasePageModel<out BaseItem>,
/**
* Activity 或 Fragment
* 1. 提供 Lifecycle
* 2. 提供 请求参数; 这里全是用 map -> JsonBody 方式提交参数;
*/
private val mView: PagingView
) {
private val mAdapter = adapter as BaseAdapter<BaseItem>
private var mEnabled: LoadMoreAdapter.Enabled? = null fun load(){
LoadMoreWrapper.with(mRecycle.adapter).apply{
setShowNoMoreEnabled(true) // enable show NoMoreView,default false
setListener { enabled: LoadMoreAdapter.Enabled ->
mEnabled = enabled val param = ArrayMap<String, Any>()
mView.prepareMap(param)
pageModel.loadData(param)
}
}.into(mRecycle) // 数据变更时, 刷新列表
pageModel.listData.observe(mView){
mAdapter.submitList(it)
} // 监听没有更多的状态;
// 当页码超出, 或当前页数据不满一页时, 没有更多
// 当页面下拉刷新时,重新启动 loadMore
pageModel.loadEnabled.observe(mView){
setEnabled(it)
}
} /**
* 控制加载更多功能; false: 显示没有更过; true: 滚动到底时触发 loadMore
*/
private fun setEnabled(enabled: Boolean) {
mEnabled?.let {
it.loadMoreEnabled = enabled
if(enabled){
mRecycle.adapter?.notifyItemChanged(mRecycle.adapter?.itemCount ?: 0)
}
}
} /**
* Activity 或 Fragment 需要实现它
*/
interface PagingView : LifecycleOwner {
/**
* 绑定额外请求参数;
*/
fun prepareMap(map: ArrayMap<String, Any>){}
}
}
4.使用
需要实现 MyPageHelper.PagingView; 重写 prepareMap() 提供请求参数
然后初始化 Adapter, RecycleView, Helper;
下拉刷新, 也可以写在 Helper 中;
class CheckPageFragment : BaseMVVMFragment<CheckModel, LayoutRecycleBinding>(),
MyPageHelper.PagingView { private lateinit var mAdapter: SingleChoiceAdapter<CheckEntity>
private var mHelper: MyPageHelper? = null override fun getLayoutId(): Int = R.layout.layout_recycle override fun onLazyLoad() {
//初始化 Adapter 及 RecycleView
mAdapter = SingleChoiceAdapter(R.layout.item_test_choise)
mDataBind.rvRecycle.let {
it.layoutManager = LinearLayoutManager(mActivity)
it.adapter = mAdapter
} //初始化 Helper
mViewModel?.let {
mHelper = MyPageHelper(mAdapter, mDataBind.rvRecycle, it, this)
mHelper?.load()
} //swipeRefresh
mDataBind.swipeRefresh.setOnRefreshListener {
mViewModel?.reload()
}
mViewModel?.refreshEnabled?.observe(this){
mDataBind.swipeRefresh.isRefreshing = it
}
}
}
最新文章
- MD5 加密
- SQL2008代理作业出现错误: c001f011维护计划创建失败的解决方法
- VC++ 回调函数及使用方法(转)
- 如何在Rails中执行Get/Post/Put请求
- mac 安装使用 webp 来压缩图片
- python time模块详解(转)
- hive 操作(转)
- 马士兵 Servlet_JSP(2) JSP源代码)
- multiset集合容器的集合运算:并、交、差
- .net嵌入c#代码(投票练习)
- 机器学习技法:06 Support Vector Regression
- 一个js的动画,以前以为只有flash可以实现
- JDK动态代理[4]----ProxyGenerator生成代理类的字节码文件解析
- float、absolute、inline-block三者区别
- SQL server SELECT 语句的基本结构
- 开发属于自己的Web服务器
- c# 链接mongDB集群实战开发3
- 大数据和hadoop有什么关系?
- php如何解决多线程同时读写一个文件的问题
- 直播 背景 技术体系 乐视云直播Demo