简要介绍
Retrofit是当前应用非常广泛的网络请求框架,而Coroutines则是Kotlin中用于执行异步任务的框架,比RxJava还要方便易用,本文将展示一个采用Coroutines+Retrofit的网络请求demo. 若想了解RxJava+Retrofit,可参考《RxJava+Retrofit实现网络请求》
集成步骤
- app工程的build.gradle中添加依赖
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1"
implementation "com.squareup.retrofit2:retrofit:2.5.0"
implementation "com.squareup.retrofit2:converter-gson:2.5.0"
implementation "com.squareup.okhttp3:logging-interceptor:3.11.0"
implementation "com.squareup.okhttp3:okhttp:3.12.2"
- 在AndroidManifest.xml中添加权限
<uses-permission android:name="android.permission.INTERNET"/>
- 添加数据类Task
data class Task(var id: Int, var name: String?)
- 添加网络请求类NetworkService
interface NetworkService {
@GET("cxyzy1/coroutineRetrofitDemo/master/data.json")
fun query(): Deferred<Task>
}
- 添加CoroutineCallAdapterFactory
class CoroutineCallAdapterFactory private constructor() : CallAdapter.Factory() {
companion object {
@JvmStatic @JvmName("create")
operator fun invoke() = CoroutineCallAdapterFactory()
}
override fun get(
returnType: Type,
annotations: Array<out Annotation>,
retrofit: Retrofit
): CallAdapter<*, *>? {
if (Deferred::class.java != getRawType(returnType)) {
return null
}
if (returnType !is ParameterizedType) {
throw IllegalStateException(
"Deferred return type must be parameterized as Deferred<Foo> or Deferred<out Foo>")
}
val responseType = getParameterUpperBound(0, returnType)
val rawDeferredType = getRawType(responseType)
return if (rawDeferredType == Response::class.java) {
if (responseType !is ParameterizedType) {
throw IllegalStateException(
"Response must be parameterized as Response<Foo> or Response<out Foo>")
}
ResponseCallAdapter<Any>(getParameterUpperBound(0, responseType))
} else {
BodyCallAdapter<Any>(responseType)
}
}
private class BodyCallAdapter<T>(
private val responseType: Type
) : CallAdapter<T, Deferred<T>> {
override fun responseType() = responseType
override fun adapt(call: Call<T>): Deferred<T> {
val deferred = CompletableDeferred<T>()
deferred.invokeOnCompletion {
if (deferred.isCancelled) {
call.cancel()
}
}
call.enqueue(object : Callback<T> {
override fun onFailure(call: Call<T>, t: Throwable) {
deferred.completeExceptionally(t)
}
override fun onResponse(call: Call<T>, response: Response<T>) {
if (response.isSuccessful) {
deferred.complete(response.body()!!)
} else {
deferred.completeExceptionally(HttpException(response))
}
}
})
return deferred
}
}
private class ResponseCallAdapter<T>(
private val responseType: Type
) : CallAdapter<T, Deferred<Response<T>>> {
override fun responseType() = responseType
override fun adapt(call: Call<T>): Deferred<Response<T>> {
val deferred = CompletableDeferred<Response<T>>()
deferred.invokeOnCompletion {
if (deferred.isCancelled) {
call.cancel()
}
}
call.enqueue(object : Callback<T> {
override fun onFailure(call: Call<T>, t: Throwable) {
deferred.completeExceptionally(t)
}
override fun onResponse(call: Call<T>, response: Response<T>) {
deferred.complete(response)
}
})
return deferred
}
}
}
- activity中调用
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
queryData()
}
private fun queryData() {
val retrofit = Retrofit.Builder()
.baseUrl("https://raw.githubusercontent.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.build()
val networkService = retrofit.create(NetworkService::class.java)
GlobalScope.launch(Dispatchers.Main) {
val result = withContext(Dispatchers.IO) { networkService.query() }
contentTv.text = result.await().toString()
}
}
}
网络请求结果截图
Demo源代码
https://github.com/cxyzy1/coroutineRetrofitDemo
安卓开发技术分享: https://www.jianshu.com/p/442339952f26
点击关注专辑,查看最新技术分享
更多技术总结好文,请关注:「程序园中猿」
网友评论