Android秀翻天的操作——使用协程进行网络请求

/   今日科技快讯   /

昨日,据路透社报道,谷歌在周二被提起一项集体诉讼:被指控通过设置为“隐身”模式的谷歌浏览器跟踪用户的互联网使用,而侵犯了数百万用户的隐私。诉讼在美国加州圣何塞联邦法院提起,寻求向谷歌索赔至少50亿美元。

/   作者简介   /

本篇文章来自catzifeng的投稿,分享了在Android中如何使用协程进行网络操作,希望对大家有所帮助!同时也感谢作者贡献的精彩文章!

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的协程还有诸多骚操作,各位道友自行挖掘,一定会挖到珍宝仙器。(这么骚的操作,你不准备点个赞吗?)

推荐阅读:

这本《第三行代码》,让大家久等了!

我新开发了一个特别好用的开源库

时隔两年,LitePal终于又更新了!

欢迎关注我的公众号

学习技术或投稿

长按上图,识别图中二维码即可关注

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值