retrofit2.6+kotlin协程中 onFailure回调的处理

先引入依赖

//这个是google官方扩展的ViewModel库支持协程操作
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'

//kotlin协程依赖
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.1'

//retrofit2.6以上
implementation 'com.squareup.retrofit2:retrofit:2.6.2'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'

implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'

初始化网络设置

object RetrofitClient {
    val BASE_URL = "https://wanandroid.com"
    val api by lazy {
        val retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(CoroutineCallAdapterFactory.invoke())
            .build()
        return@lazy retrofit.create(RequestService::class.java)
    }
}

interface RequestService {
    @GET("wxarticle/chapters/json")
    suspend fun getData(): ArticleData
}

data class ArticleData(
    val `data`: List?,
    val errorCode: Int,
    val errorMsg: String?
)

data class Data(
    val courseId: Int,
    val id: Int,
    val name: String,
    val order: Int,
    val parentChapterId: Int,
    val userControlSetTop: Boolean,
    val visible: Int
)
class CommViewModel : ViewModel() {
     fun getData() {
        viewModelScope.launch {
            val data = RetrofitClient.api.getData1()
            Log.i(TAG, ": ${data.data}")
        }
    }
    
    override fun onCleared() {
        super.onCleared()
        //ViewModel销毁的时候,取消所有的协程
        viewModelScope.coroutineContext.cancelChildren()
    }

    companion object {
        val TAG: String = CommViewModel::class.java.simpleName
    }
}

在网上看了很多的博客,大部分都是如上这样子介绍一些比较简单的使用,但是如果要深入一点,比如网络请求的onFailure判断,在网上翻阅到的资料并不是太满意,最后还是自己封装一个。

1.新建一个ApiResponse类,主要用来包装网络请求返回的onResponse、onFailure数据

 class ApiResponse {
    var code = SUCCESS_CODE
    var body: T? = null
    var msg: String? = null

    constructor(response: Response) {
        body = response.body()
    }

    constructor(t: T) {
        body = t
    }

    constructor(throwable: Throwable) {
        body = null
        code = ERROR_CODE

        //对异常进行判断,这个是我随便写的一点,可以写一个工具类给封装起来
        msg = when (throwable) {
            is SocketTimeoutException -> "超时"
            is HttpException -> {
                when (throwable.code()) {
                    404 -> "没有找到合适的资源"
                    500 -> "服务器内部错误"
                    else -> throwable.message()
                }
            }
            is JSONException -> "json解析异常"
            is UnknownHostException -> "网络异常"
            else -> throwable.message
        }
    }

    companion object {
        private const val TAG = "ApiResponse"
        const val ERROR_CODE = 99999
        const val SUCCESS_CODE = 200
        fun error(throwable: Throwable): ApiResponse<*> {
            return ApiResponse(throwable)
        }
    }
}

2.再使用kotlin的扩展函数对ViewModel进行扩展 ,让所有的ViewModel类都能使用 call() 方法,主要是进行异常的逻辑处理

suspend fun  ViewModel.call(job: suspend () -> T): ApiResponse {
    return try {
        ApiResponse(job())
    } catch (e: java.lang.Exception) {
        ApiResponse(e)
    }
}

请求最后会变成如下这样

fun getData() {
        viewModelScope.launch {
            val data = call {
                RetrofitClient.api.getData1()
            }
            //表示有异常
            if (data.code == ApiResponse.ERROR_CODE) {
                Log.i(TAG, ": ${data.msg}")
                return@launch
            }
            //取出我们后台接口返回的数据
            val body = data.body
            body?.let {
                if (it.errorCode == ApiResponse.SUCCESS_CODE) {
                    Log.i(TAG, ": ${it.data}")
                }
            }
        }
    }

你可能感兴趣的:(retrofit2.6+kotlin协程中 onFailure回调的处理)