【Jetpack篇】协程+Retrofit网络请求状态封装实战

本文介绍了如何在Android应用中使用Jetpack、Kotlin协程和Retrofit进行网络请求,详细讲解了如何封装网络请求状态,包括Error、Loading和Empty状态,以及如何处理网络异常。此外,还探讨了在使用协程时遇到的问题,如异常处理和LiveData的单次通知问题,并提出了解决方案。
摘要由CSDN通过智能技术生成

前言

在App中,对于网络请求状态一般性的就分为加载中、请求错误、请求成功、请求成功但数据为null。为了用户体验,不同的状态需要对用户展示不同的界面,例如网络异常的提醒,点击重新请求等。

之前项目一直都是以Retrofit+RxJava+OkHttp为网络请求框架,RxJava已经很好的封装了不同的请求状态,onSubscribe、onNext、onError等,只需要在不同的回调中做出相应的动作就ok了。

RxJava很好用,但随着新技术的出现,RxJava的可替代性也就越高。Kotlin的协程就是这么一个存在。

本文是以Jetpack架构为基础,协程+Retrofit+Okhttp为网络请求框架,对不同的请求状态(loading,error,empty等)做了封装,让开发者不用再去关心哪里需要loading,哪里需要展示error提示。

同时,在封装的过程中,Jetpack和协程的使用也存在着几个坑,本文也将一一描述。

协程的基本使用

API:https://www.wanandroid.com/project/tree/json 来自鸿洋大大的wanandroid

如果需要使用协程,则添加依赖

dependencies {
   
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
}

在Retrofit2.6.0前,我们使用协程,api请求后返回的数据可以用Call或者Defeerd包裹处理,2.6后,可以直接返回数据,只不过需要加上suspend的修饰,如下:

interface ProjectApi {
   

    @GET("project/tree/json")
    suspend fun loadProjectTree(): BaseResp<List<ProjectTree>>
}

因为使用的是Jetpack架构,所以将整个网络请求主要分为UI、ViewModel、Repository三层,以LiveData为媒介进行通信。

首先是Repository层进行网络请求,

 class ProjectRepo{
   
    private lateinit var mService: ProjectApi

    init {
   
        mService = RetrofitManager.initRetrofit().getService(ProjectApi::class.java)
    }

    suspend fun loadProjectTree(): List<ProjectTree> {
   
        return mService.loadProjectTree()
    }
 }

利用Retrofit和OkHttp创建了一个apiService,内部细节在这里就先不展开,接着直接调用loadProjectTree()进行网络请求,将数据返回。loadProjectTree()用suspend关键字进行标记,Kotlin 利用此关键字强制从协程内调用函数。

接着ViewModel层,

class ProjectViewModel : ViewModel(){
   
      //LiveData
      val mProjectTreeLiveData = MutableLiveData<List<ProjectTree>>()
      fun loadProjectTree() {
   
        viewModelScope.launch(Dispatchers.IO) {
   
            val data = mRepo.loadProjectTree()
            mProjectTreeLiveData.postValue(data)
        }
    }
}

创建类ProjectViewModel并继承ViewModel,内部新建一个LiveData做UI通信使用,利用viewModelScope.launch(Dispatchers.IO) 创建一个新的协程,然后在 I/O 线程上执行网络请求,请求的数据利用LiveData通知给UI。

这里提到了viewModelScope.launch(Dispatchers.IO)viewModelScope是一个协程的作用域,ViewModel KTX 扩展中已经将此作用域封装好,直接使用就可以。Dispatchers.IO 表示此协程在 I/O线程上执行,而launch则是创建一个新的协程。

最后是UI层,

class ProjectFragment : Fragment {
   

    override fun initData() {
   
        //请求数据,调用loadProjectTree
        mViewModel?.loadProjectTree()
        mViewModel?.mProjectTreeLiveData?.observe(this, Observer {
   
            //更新UI
        })
    }

UI层开始调用ViewModel的请求方法执行网络请求,LiveData注册一个观察者,观察数据变化,并且更新UI。

到这里,网络请求的逻辑基本上通顺了。

在一切环境正常的情况下,上面的请求是可以的,但是app还存在网络不畅,异常,数据为null的情况,上述就不在满足要求了,接下来就开始对数据异常的情况进行处理。

网络请求异常处理

对于协程异常的处理,Android开发者的官网上也给出了答案(https://developer.android.google.cn/kotlin/coroutines?hl=zh-cn ) ,直接对网络请求进行一个try-catch处理,发生异常了,直接在catch中做出相应动作就ok了,我们就来看看具体实现。

class ProjectViewModel : ViewModel(){
   
      //LiveData
      val mProjectTreeLiveData = MutableLiveData<List<ProjectTree>>()
      fun loadProjectTree() {
   
        viewModelScope.launch(Dispatchers.IO) {
   
          try {
   
                  val data = mRepo.loadProjectTree()
                  mProjectTreeLiveData.postValue(data
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值