一、前言
前几天发布了一篇【Jetpack篇】协程+Retrofit网络请求状态封装实战,在评论区里也收到了一些同僚的反馈:
…
具体问题可以直接移步到上一篇评论区查看。
因为有几个问题点还蛮重要,所以就上一篇文章新增了一些内容,主要如下:
- ✅ 新增局部状态管理。如同一个页面多个接口,可以分别管理状态切换;
- ✅ UI层新增Error,Empty,Success的Callback,开发者可以自由选择是否监听,处理业务逻辑更直观、方便;
- ✅ 结合第三方库loadSir,统一切换UI。
- ✅ 请求调用更加简单
好了,正文开始。
二、局部请求状态管理
很多时候app开发,存在同一个界面不同接口的情况,两个接口同时请求,一个成功一个失败,这个时候成功接口继续显示自己的页面,失败接口则显示Error提示界面,如下图
上一篇的封装是将errorLiveData和loadingLiveData全局封装在BaseFragment中,而他们的创建也是在BaseViewModel中,这样就导致多个接口同时请求时,如果某个接口发送错误,就无法区分错误来自哪里。
如果需要每个接口单独管理自己的状态,那么就需要在ViewModel中创建多个erroeLiveData,这样问题是可以解决,但是会导致代码非常冗余。既然需要每个接口管理不同状态,那就可以新建一个既包含请求返回结果又包含不同状态值的LiveData,将之命名为StateLiveData
/**
* MutableLiveData,用于将请求状态分发给UI
*/
class StateLiveData<T> : MutableLiveData<BaseResp<T>>() {
}
而BaseResp中除了请求返回值的公共json外,还需要添加上不同的状态值,我们将状态值分为( STATE_CREATE,STATE_LOADING,STATE_SUCCESS,STATE_COMPLETED,STATE_EMPTY,STATE_FAILED, STATE_ERROR,STATE_UNKNOWN)几种
enum class DataState {
STATE_CREATE,//创建
STATE_LOADING,//加载中
STATE_SUCCESS,//成功
STATE_COMPLETED,//完成
STATE_EMPTY,//数据为null
STATE_FAILED,//接口请求成功但是服务器返回error
STATE_ERROR,//请求失败
STATE_UNKNOWN//未知
}
将DataState添加到BaseResp中,
/**
* json返回的基本类型
*/
class BaseResp<T>{
var errorCode = -1
var errorMsg: String? = null
var data: T? = null
private set
var dataState: DataState? = null
var error: Throwable? = null
val isSuccess: Boolean
get() = errorCode == 0
}
那StateLiveData该如何使用呢?
我们都知道数据请求会有不同的结果,成功,异常或者数据为null,那么就可以利用不同的结果,将相应的状态设置在BaseResp的DataState中。直接进入到数据请求Repository层,对上篇异常处理做了改进。
open class BaseRepository {
/**
* repo 请求数据的公共方法,
* 在不同状态下先设置 baseResp.dataState的值,最后将dataState 的状态通知给UI
*/
suspend fun <T : Any> executeResp(
block: suspend () -> BaseResp<T>,
stateLiveData: StateLiveData<T>
) {
var baseResp = BaseResp<T>()
try {
baseResp.dataState = DataState.STATE_LOADING
//开始请求数据
val invoke = block.invoke()
//将结果复制给baseResp
baseResp = invoke
if