Kotlin中像RxHttp一样优雅的使用Retrofit

4,025 阅读1分钟

Kotlin中像RxHttp一样优雅的使用Retrofit

1.简介

Retrofit对协程的支持非常的简陋。在kotlin中使用不符合kotlin的优雅。 RxHttp在协程中使用非常方便。但是我们项目又已经使用了Retrofit怎么办,那就让Retrofit像RxHttp一样使用 RxHttp

2.源码地址

GitHub

3.本框架使用

添加依赖

Download

implementation "io.github.cnoke.ktnet:api:?"

写一个网络请求数据基类

open class ApiResponse<T>(
    var data: T? = null,
    var errorCode: String = "",
    var errorMsg: String = ""
)

实现com.cnoke.net.factory.GsonResponseBodyConverter

class MyGsonResponseBodyConverter : GsonResponseBodyConverter() {

    override fun convert(value: ResponseBody): Any {
        val jsonReader = gson.newJsonReader(value.charStream())
        val data = adapter.read(jsonReader) as ApiResponse<*>
        val t = data.data

        val listData = t as? ApiPagerResponse<*>
        if (listData != null) {
            //如果返回值值列表封装类,且是第一页并且空数据 那么给空异常 让界面显示空
            if (listData.isRefresh() && listData.isEmpty()) {
                throw ParseException(NetConstant.EMPTY_CODE, data.errorMsg)
            }
        }

        // errCode 不等于 SUCCESS_CODE,抛出异常
        if (data.errorCode != NetConstant.SUCCESS_CODE) {
            throw ParseException(data.errorCode, data.errorMsg)
        }

        return t!!
    }

}

进行网络请求

interface TestServer {
    @GET("banner/json")
    suspend fun awaitBanner(): Await<List<Banner>>
}

val okHttpClient = OkHttpClient.Builder()
            .addInterceptor(HeadInterceptor())
            .addInterceptor(LogInterceptor())
            .build()

/**
 * 必须使用ApiResultCallAdapterFactory()
 * GsonConverterFactory.create(ApiResponse::class.java,MyGsonResponseBodyConverter())
 * GsonConverterFactory.create传入网络请求数据结构基类,以及数据解析类
 */
val retrofit = Retrofit.Builder()
            .client(okHttpClient)
            .baseUrl("https://www.wanandroid.com/")
            .addCallAdapterFactory(ApiResultCallAdapterFactory())
            .addConverterFactory(GsonConverterFactory.create(ApiResponse::class.java,MyGsonResponseBodyConverter()))
            .build()
val service: TestServer = retrofit.create(TestServer::class.java)
lifecycleScope.launch {
       val banner = service.awaitBanner().await()
}

异步请求同步请求,异常捕获参考如下try开头的会捕获异常,非try开头不会捕获。 其他各种用法请参考RxHttp 操作符使用(目前暂不支持文件下载,文件上传) RxHttp 2000+star,协程请求,仅需三步 - 掘金 (juejin.cn)

fun banner(){
    lifecycleScope.launch {
        //单独处理异常 tryAwait会处理异常,如果异常返回空
        val awaitBanner = service.awaitBanner().tryAwait()
        awaitBanner?.let {
            for(banner in it){
                Log.e("awaitBanner",banner.title)
            }
        }

        /**
         * 不处理异常 异常会直接抛出,统一处理
         */
        val awaitBannerError = service.awaitBanner().await()
    }
}

/**
 * 串行 await
 */
fun serial(){
    lifecycleScope.launch {
        //先调用第一个接口await
        val awaitBanner1 = service.awaitBanner().await()
        //第一个接口完成后调用第二个接口
        val awaitBanner2 = service.awaitBanner().await()
    }
}

/**
 * 并行 async
 */
fun parallel(){
    lifecycleScope.launch {
        val awaitBanner1 = service.awaitBanner().async(this)
        val awaitBanner2 = service.awaitBanner().async(this)

        //两个接口一起调用
        awaitBanner1.await()
        awaitBanner2.await()
    }
}