写点什么

【Jetpack 篇】协程,腾讯 T3 团队整理

用户头像
Android架构
关注
发布于: 刚刚

STATE_UNKNOWN//未知}


将 DataState 添加到 BaseResp 中,


/**


  • json 返回的基本类型*/class BaseResp<T>{var errorCode = -1var errorMsg: String? = nullvar data: T? = nullprivate setvar dataState: DataState? = nullvar error: Throwable? = nullval isSuccess: Booleanget() = 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()//将结果复制给 baseRespbaseResp = invokeif (baseResp.errorCode == 0) {//请求成功,判断数据是否为空,//因为数据有多种类型,需要自己设置类型进行判断 if (baseResp.data == null || baseResp.data is List<> && (baseResp.data as List<*>).size == 0) {//TODO: 数据为空,结构变化时需要修改判空条件 baseResp.dataState = DataState.STATE_EMPTY} else {//请求成功并且数据为空的情况下,为 STATE_SUCCESSbaseResp.dataState = DataState.STATE_SUCCESS}


} else {//服务器请求错误 baseResp.dataState = DataState.STATE_FAILED}} catch (e: Exception) {//非后台返回错误,捕获到的异常 baseResp.dataState = DataState.STATE_ERRORbaseResp.error = e} finally {stateLiveData.postValue(baseResp)}}}


executeResp()为数据请求的公共方法,该方法传入了两个参数,第一个是将数据请求函数当作参数,第二个就是上面新建的StateLiveData


方法一开始就新建了一个 BaseResp()对象,将DataState.STATE_LOADING状态设置给 BaseResp 的 dataState,接着开始对数据请求进行异常处理(具体可查看上一篇),如果 code=0 表示接口请求成功,否则表示接口请求成功,服务器返回错误。在 code=0 时,对返回数据进行判空处理,因为数据有多种类型,这里需要自己设置类型进行判断,为空就将状态设置为DataState.STATE_EMPTY,否则为


DataState.STATE_SUCCESS。如果抛出异常,则将状态设置为DataState.STATE_ERROR,在请求结束后,利用stateLiveData将带有状态的 baseResp 分发给 UI。


到这里,请求状态都设置完成,接下来只需要根据不同状态,开始进行界面切换处理。

三、结合 LoadSir 界面切换

LoadSir是一个加载反馈页管理框架,状态页自动切换,具体使用在这里就不描述了,需要的可移步github查看。


LiveData 接收数据变化时,UI 会先注册一个接收事件的观察者,接收到请求的数据后就进行 UI 更新,第二节里将不同状态也添加到了数据中,要想对状态也进行监听的话,就需要对 Observer 进行状态处理。


/**


  • LiveData Observer 的一个类,

  • 主要结合 LoadSir,根据 BaseResp 里面的 State 分别加载不同的 UI,如 Loading,Error

  • 同时重写 onChanged 回调,分为 onDataChange,onDataEmpty,onError,

  • 开发者可以在 UI 层,每个接口请求时,直接创建 IStateObserver,重写相应 callback。*/abstract class IStateObserver<T>(view: View?) : Observer<BaseResp<T>>, Callback.OnReloadListener {private var mLoadService: LoadService<Any>? = null


init {if (view != null) {mLoadService = LoadSir.getDefault().register(view, this,Convertor<BaseResp<T>> { t ->var resultCode: Class<out Callback> = SuccessCallback::class.java


when (t?.dataState) {


//数据刚开始请求,loadingDataState.STATE_CREATE, DataState.STATE_LOADING -> resultCode =LoadingCallback::class.java//请求成功 DataState.STATE_SUCC


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


ESS -> resultCode = SuccessCallback::class.java//数据为空 DataState.STATE_EMPTY -> resultCode =EmptyCallback::class.javaDataState.STATE_FAILED ,DataState.STATE_ERROR -> {val error: Throwable? = t.erroronError(error)//可以根据不同的错误类型,设置错误界面时的 UIif (error is HttpException) {//网络错误} else if (error is ConnectException) {//无网络连接} else if (error is InterruptedIOException) {//连接超时} else if (error is JsonParseException|| error is JSONException|| error is ParseException) {//解析错误} else {//未知错误}resultCode = ErrorCallback::class.java}DataState.STATE_COMPLETED, DataState.STATE_UNKNOWN -> {}else -> {}}Log.d(TAG, "resultCode :$resultCode ")resultCode})}


}


override fun onChanged(t: BaseResp<T>) {Log.d(TAG, "onChanged: ${t.dataState}")


when (t.dataState) {DataState.STATE_SUCCESS -> {//请求成功,数据不为 nullonDataChange(t.data)}


DataState.STATE_EMPTY -> {//数据为空 onDataEmpty()}


DataState.STATE_FAILED,DataState.STATE_ERROR->{//请求错误 t.error?.let { onError(it) }}else -> { }}


//加载不同状态界面 Log.d(TAG, "onChanged: mLoadService $mLoadService")


mLoadService?.showWithConvertor(t)


}


/**


  • 请求数据且数据不为空*/open fun onDataChange(data: T?) {


}


/**


  • 请求成功,但数据为空*/open fun onDataEmpty() {


}


/**


  • 请求错误*/open fun onError(e: Throwable?) {


}}


IStateObserverObserver接口的实现类,参数传入了一个 View,而这个 View 就是你所要替换的界面,这也就是同个界面,不同模块显示异常不同的关键所在。因为是结合 Loadsir,首先需要初始化 LoadService,再者通过 dataState 的状态值,设置不同的 Callback,例如 Loading 时,设置为LoadingCallback,Error 时,设置为ErrorCallback,Empty 时设置为EmptyCallback,设置完成后,在 onChanged 回调中统一调用showWithConvertor,也就是切换界面的操作。


而在 onChange 回调中,同样根据状态值,分别分发onDataChangeonDataEmptyonError的通知。


到这里,完成了不同状态界面切换和状态通知的分发工作。


四、如何使用

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
【Jetpack篇】协程,腾讯T3团队整理