目前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 } } }



