Kotlin协程巩固

网友投稿 800 2022-09-08

Kotlin协程巩固

Kotlin协程巩固

该篇基于​​Kotlin 协程学习​​,国庆放假来巩固一下知识。

Retrofit更新到 ​​2.6.0​​​的版本后,引入了对协程的支持,这样更利于我们打造优雅的网络框架。但是现在大部分Android框架都用 ​​RxJava + Retrofit​​的,而协程本身是和RxJava功能重合的(便于切线程),所以我需要理清这两者的区别,在使用时合理取舍。

1. Retrofit对协程的支持

​​2.6.0​​版本,Retrofit可以使用协程来进行网络请求。我们先看看前后有什么区别。

1.1 原始的Retrofit使用

Api定义如下:

interface Api { @GET("user/{user}/repos") fun listRepos(@Path("user") user: String): Call}

接着在代码中使用:

val apiService = Retrofit.Builder() .baseUrl(" .build().create(Api::class.java) apiService.listRepos("Rikkatheworld").enqueue(object : Callback { override fun onFailure(call: Call?, t: Throwable?) { textview.text = t?.message } override fun onResponse(call: Call?, response: Response?) { textview.text = call } }) }

1.2 使用协程的Retrofit

协程可以帮我们解决掉写回调的麻烦,所以我们可以把请求写在协程中,这也需要我们调用的Api函数需要被 ​​@suspend​​修饰

interface Api { @GET("user/{user}/repos") suspeend fun listRepos(@Path("user") user: String): ResponseBody}

接着在代码中开一个协程来消除回调:

这样来看,就真的消除了回调。但是有一个问题:上面代码的 repos是请求成功后的结果,那么失败怎么办? 目前Kotlin和Retrofit都没有给出方案,所以只能采用 ​​​try-catch​​的方法

.launch(Dispatchers.Main) { try { val repos = apiService.listRepos("Rikkatheworld") textview.text = repos.toString() } catch (e: Exception) { textview.text = e.message } }

这就比较难受了…

2. 协程与RxJava

2.1 代码的比较

RxJava的代码大家都写惯了,大概是这样的:

.listRepos("Rikkatheworld") //将请求放在后台 .subscribeOn(Schedulers.io()) //将结果的返回放在前台 .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : SingleObserver>() { fun onSubscribe(d: Disposable) { Log.d(TAG, "onSubscribe") } fun onSuccess(repo: List) { Log.d(TAG, repo[0].toString()) } fun onError(e: Throwable) { Log.e(TAG, e.message) } })

而使用协程,则可以使用 async来切线程:

.launch(Dispatchers.Main) { try { val res = async { apiService.listRepos("Rikkathewrold") } //异步获取挂起结果 textview.text = res.await().toString() //主线程更新ui } catch (e: Exception) { Log.e(TAG, "${e.message}") } }

2.2 总结

他们的共同点:

都可以切换线程都不需要嵌套

他们的不同点

RxJava需要写回调,而协程不需要RxJava链式调用,结构清晰;而协程会自己切换线程,所以代码更加简洁

RxJava和协程的功能和使用场景基本一致,而协程在结构上比RxJava更加简单,如果使用数据流,协程还可以使用 ​​Flow​​​,可以学下这篇文章:​​Kotlin协程(5)Flow​​。

而性能上,在 ​​RxJava vs. Kotlin Coroutines, a quick look​​的文章中进行了对比,因为协程在处理挂起函数的逻辑上较为复杂,所以在性能上 协程比RxJava更弱一点。 但是这是2017年的文章了,现在不知道Kotlin官方有没有进行改进。

我个人认为,以后Android开发都是Jetpack全家桶了,而Kotlin团队JetBrains又是Google“亲儿子”,所以以后Jetpack肯定会更加支持协程的, 所以我更相信KT官方会解决协程的问题,而更偏向在代码中使用协程去取代RxJava。

3. 协程的“泄漏”

在​​Kotlin 协程学习​​的第四节中,讲到了如何去取消一个协程,为什么要取消没有写的很明白,我们让协程跑完不就行了?

在Android日常的开发中,我们是不知道用户会做什么事情的,假如当前程序正在执行一个协程来执行一个耗时的任务,而用户在任务还没有完成的时候把页面关了(就是会走 ​​onDestroy()​​​那种),那我们的协程也需要关闭才对,不然的话,协程可是会跑一个线程的,它继续跑下去的,GC就会受不了,导致产生“内存泄漏”。因为 一个线程就是一个 ​​GC Root​​。

所以在面试中, 面试官所说的 “协程泄漏”其实就等于 “线程的内存泄漏”,它本质上和 ​​AsyncTask​​的泄漏是样的。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:《重构》学习(2)拆分逻辑与多态使用
下一篇:两个很实用的Python装饰器详解(python中的装饰器)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~