catzifeng的博客地址:
https://blog.csdn.net/catzifeng
/ 前言 /
Android网络界发展至今已经出现过无数风流框架,看先祖HttpURLConnection老矣,HttpClient也早已隐退,而那android-async-http力不从心却也封刀,但江湖却还流传着它的故事,有那谷歌亲儿子volley独占中州,笑迎四面八方来客,OkHttp不慌不急,稳占其余大洲,更有它那亲爹Retrofit默默支撑着它,使得各位风骚道友能够有安稳的栖身之地。
异步界RxJava“异军” 突起,揍扁太子AsnyTask逐渐统一异步界,成为异步界的霸主,RxJava虽不闻不问网络界的是非,但是偶然的一次相遇,使得RxJava和Retrofit如胶似漆,殊不知,这是Retrofit的计谋,想要借助RxJava这个工具人,壮大自己的实力,进一步统一网络界!
又不知过了多少年岁,天地宇宙各界各地突然出现崩塌迹象,无端出现莫名其妙的裂缝!裂缝每时每刻都在将每片区域空气中的Java吸走!十分霸道!各界每位风骚道友都人心惶惶,没有了Java,道友们就不能够呼吸,正当道友们岌岌可危之时,那些裂缝竟然反吐一种令人心旷神怡的气体——Kotlin,道友们呼吸到Kotlin之后,神宁瞬间安静,甚至表情中都泛有一丝春光!大家逐渐都爱上了这个新的气体。他们还发现,在练功时如果使用Kotlin, 每个大周天提炼的灵力竟然比使用Java多出一倍有余!
不仅仅是各位道友注意到了Kotlin的神奇之处,想那妖艳贱货Retrofit也早就领会Kotlin之妙用,终有一天,Retrofit不满RxJava花心浪荡,摔杯举剑,只见那秀剑飞起,在手中720度托马斯回旋,“撕拉”一声,割袍断义,与 RxJava 分道扬镳……
/ Kotlin协程 /
在Kotlin 1.3版本中 协程 逐步稳定,我们可以放心大胆的使用,关于 协程 的概念和使用详解,我无法做出太多介绍,这东西太玄学了,因为没有开放源码,江湖上没有几个道友能够彻底理解,或许也只有几位不出世的高人才能够熟知吧。
协程官方文档:
https://www.kotlincn.net/docs/reference/coroutines/coroutines-guide.html
协程可看作是一个轻量级的线程,协程必须依附在某个线程,类似于守护线程,当协程依附的线程被干掉(或者正常结束),那么这个协程也会挂掉。
/ 协程和Retrofit /
关于Retrofit如何使用,道友们肯定很是熟知:
interface ApiService{
@GET("url/request")
fun doRequest():Call<ResponseBody>
}
fun main() {
Retrofit.Builder().build() //这 里 只 是 意 思 意 思 一 下 ! ! !
.create(ApiService::class.java)
.doRequest()
.enqueue(object : Callback<ResponseBody> {
override fun onFailure(call: Call<ResponseBody>, t: Throwable) { }
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) { }
})
}
在2019年2月16号 ,大神JakeWharton对Retrofit提交了一个重要的代码:
支持了协程!当我们点进去的时候,可以看看关键的文件和代码。一个名叫KotlinExtensions.kt的文件增加了3个Kotlin扩展方法。
这3个方法就是用来配合协程一起来搞骚操作的。如果道友们因为种种原因,不能更新Retrofit比较新的版本,那么可以尝试自己去复制这几个方法到自己的扩展函数中。
GitHub地址:
https://github.com/square/retrofit/commit/b761518aa174c7b0512b73f2fe70e2e908f24081#diff-afbee4f0294010620954bfa945075192
/ 预备工作 /
准备好Retrofit
如上一小节所述,如果你没法更新Retrofit ,那么你就在自己的扩展文件中添加一个扩展方法即可,这3个方法没必要都写上去,他们的本质都是一样的,所以我们只要挑选一个基本款车型即可,然后随你怎么加装配件都行:
/**
* 某 KtExtension.kt 文件
*/suspend fun <T : Any> Call<T>.await(): Response<T> {
return suspendCancellableCoroutine { continuation ->
//车况异常处理装置
continuation.invokeOnCancellation {
cancel()
}
enqueue(object : Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
//1.基本款装置
continuation.resume(response)
//2.加装改款胎压检测装置 <需替换基本款装置>
if (response.isSuccessful) {
continuation.resume(response.body())
} else {
continuation.resumeWithException(HttpException(response))
}
}
override fun onFailure(call: Call<T>, t: Throwable) {
//道路异常处理装置
continuation.resumeWithException(t)
}
})
}
}
准备好协程
我们先导入Android的协程扩展:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5'
这样我们就能够轻松拿到主线程的协程上下文环境。
编写全局(或者局部,随你心情定)协程代码块方法:
/**
* 某 KtExtension.kt 文件
* 默认主线程的协程
*/fun launch(block: suspend (CoroutineScope) -> Unit,
error: ((e: Exception) -> Unit)? = null,
context: CoroutineContext = Dispatchers.Main): Job {
return GlobalScope.launch(context + CoroutineExceptionHandler { _, e ->
Log.e("==>coroutineException", e.message) //1
}) {
try {
block(this)
} catch (e: Exception) { //2
Log.e("==>coroutineError", e.message)
if (error != null) {
error(e)
}
}
}
}
注意上面有两个异常捕获:1. 捕获整个协程的异常;2.捕获协程代码块执行的异常。为了保证程序的稳定,两个都必须要有。
/ 使用 /
先定义请求接口
interface LoginApi {
/**
* 获取登录二维码
*/ @GET("/xxx/xxx/xxx")
fun getLoginQRBitmap(): Call<BaseResponse<String?>>
}
创建协程作用域
因为是全局方法,所以在哪里我们都能够调用
launch({
//MainNet.server()是封装了Retrofit的过程,此过程就不展示了
val bitmapEntity = MainNet.server(LoginApi::class.java).getLoginQRBitmap().await()
println("二维码地址为:${bitmapEntity.data}")
//加载二维码,可以进行更新 UI 的操作
initBitmap(bitmapEntity.data)
}, {
//TODO 网络请求异常处理
})
控制中断协程
launch这个方法会返回一个Job,这个Job就相当于RxJava的Disposable,可以调用其方法进行中断协程:
val job = launch({
... ...
})
//中断协程
job.cancel()
简单说明
因为是依附在主线程的协程,所以你 完全可以在launch的作用域中更新UI,又因为是协程,所以网络请求的这个过程中你完全不必当心会阻塞UI线程。
/ 总结 /
Kotlin的协程还有诸多骚操作,各位道友自行挖掘,一定会挖到珍宝仙器。(这么骚的操作,你不准备点个赞吗?)
关注我获取更多知识或者投稿
如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: http://leetcode.jp/android编程-android秀翻天的操作-使用协程进行网络请求/