Coroutines+Retrofit实现网络请求

作者: 蓝不蓝编程 | 来源:发表于2019-04-09 15:14 被阅读15次

简要介绍

Retrofit是当前应用非常广泛的网络请求框架,而Coroutines则是Kotlin中用于执行异步任务的框架,比RxJava还要方便易用,本文将展示一个采用Coroutines+Retrofit的网络请求demo. 若想了解RxJava+Retrofit,可参考《RxJava+Retrofit实现网络请求

集成步骤

  1. 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"
  1. 在AndroidManifest.xml中添加权限
<uses-permission android:name="android.permission.INTERNET"/>
  1. 添加数据类Task
    data class Task(var id: Int, var name: String?)
  2. 添加网络请求类NetworkService
interface NetworkService {
    @GET("cxyzy1/coroutineRetrofitDemo/master/data.json")
    fun query(): Deferred<Task>
}
  1. 添加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
        }
    }
}
  1. 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
点击关注专辑,查看最新技术分享
更多技术总结好文,请关注:「程序园中猿」

相关文章

网友评论

    本文标题:Coroutines+Retrofit实现网络请求

    本文链接:https://www.haomeiwen.com/subject/qunbiqtx.html