当前位置:   article > 正文

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

kotlin协程网络请求封装

前言

在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'
}
  • 1
  • 2
  • 3
  • 4

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

interface ProjectApi {
   

    @GET("project/tree/json")
    suspend fun loadProjectTree(): BaseResp<List<ProjectTree>>
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

因为使用的是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()
    }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

利用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)
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

创建类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
        })
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/267008
推荐阅读
相关标签
  

闽ICP备14008679号