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

}

}

}

文章链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: