栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android中利用OkHttp+Retrofit+kotlin协程发出网络请求

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android中利用OkHttp+Retrofit+kotlin协程发出网络请求

目前Android端流行的网络请求模式是,OkHttp+retrofit2+RxJava,但是kotlin协程横空出世之后,RxJava的某些特性与kotlin协程出现了冲突,那我们能抛开RxJava吗? 当然可以,这里,我们示范一种OkHttp+retrofit2+kotlin协程的网络请求模式。

添加依赖

模块的build.gradle添加以下依赖

dependencies {
	implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
}
创建Retrofit对象
val retrofit = Retrofit.Builder()
    .client(HttpClient.get(baseApplication.getContext(), httpParams, BuildConfig.DEBUG))
    .baseUrl(baseUrl)
    .addConverterFactory(GsonConverterFactory.create(gson))
    //这里我们改为CoroutineCallAdapterFactory
    .addCallAdapterFactory(CoroutineCallAdapterFactory()) 
    .build()
创建网路请求接口文件
interface Api {
   @POST("/api/xxx/xxx/xxx")
   fun loginAsync(@Body body: JsonObject): Deferred>
}

与RxJava不同,这里的返回值我们改为Deferred即可

封装下个ApiManager接口

理论上,上面就可以直接用了,但是我们也可以对网络请求的错误做出统一处理,所以封装一个ApiManager类

object ApiManager {
    suspend fun  request(deferred: Deferred>): HttpResponse = withContext(Dispatchers.IO) {
        try {
            return@withContext deferred.await()
        } catch (e: Exception) {
            Log.e("ApiManager", e.message)
            e.printStackTrace()
            val data = createEmpty(e.message.toString())
            val type = object : TypeToken>() {}.type
            return@withContext GsonUtils.gsonToModel(data, type) as HttpResponse
        } catch (e: Throwable) {
            Log.e("ApiManager","throwable")
            val data = createEmpty("请求错误")
            val type = object : TypeToken>() {}.type
            return@withContext GsonUtils.gsonToModel(data, type) as HttpResponse
        }
    }

    private fun createEmpty(msg: String): String {
        val map = androidx.collection.ArrayMap()
        map["code"] = 500
        map["msg"] = msg
        return GsonUtils.toJson(map)
    }
}
请求示例
    suspend fun login(userName: String, verifyCode: String): HttpResponse {
        //xxx
        body.add("clientInfo", clientInfo)
        return request(bmsApi.loginAsync(body))
    }

如上,我们可以用kotlin协程的做法,就像同步请求一样,非常优雅的做出网络请求。

原理

关键代码就在CoroutineCallAdapterFactory类中,我们可以研究下这个类,这里也示范下如何将callback改装为kotlin协程。

  private class ResponseCallAdapter(
      private val responseType: Type
  ) : CallAdapter>> {

    override fun responseType() = responseType

    override fun adapt(call: Call): Deferred> {
      val deferred = CompletableDeferred>()

      deferred.invokeOnCompletion {
        if (deferred.isCancelled) {
          call.cancel()
        }
      }
	  //进行网络请求
      call.enqueue(object : Callback {
        override fun onFailure(call: Call, t: Throwable) {
          deferred.completeExceptionally(t)
        }

        override fun onResponse(call: Call, response: Response) {
          //返回网络请求结果
          deferred.complete(response)
        }
      })

      return deferred
    }
  }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/755756.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号