Kotlin协程它不香吗?(1)

接口API链接: www.wanandroid.com/blog/show/2

interface ApiService {

companion object {

const val BASE_URL = “https://www.wanandroid.com”

}

@FormUrlEncoded

@POST(“/user/login”)

fun login(@Field(“username”) username: String,

@Field(“password”) password: String): Deferred<WanResponse>

}

Deferred是什么?它是Job的子接口。那,,,Job又是什么呢?可以简单理解,整个登录请求的过程就是会被封装成Job,然后交给协程调度器处理。但Job在完成的时候是没有返回值的,所以就有了Deferred,它的意思就是延迟,结果稍后才能拿到,它可以为任务完成时提供返回值。

根据请求后返回的json,写出返回值的数据类

data class WanResponse(val errorCode: Int,val errorMsg: String,val data: T)

data class User(val collectIds: List,val email: String,

val icon: String,val id: Int,

val password: String, val type: Int, val username: String)

之后构建一个retrofit实例,用它来进行请求登录

class ApiRepository {

val retrofit = Retrofit.Builder()

.baseUrl(ApiService.BASE_URL)

.addConverterFactory(GsonConverterFactory.create())

//添加对Deffered的支持

.addCallAdapterFactory(CoroutineCallAdapterFactory.invoke())

.build()

.create(ApiService::class.java)

fun login(name: String,password: String): Deferred<WanResponse>{

return retrofit.login(name,password)

}

}

接下来主角协程要出场了。我们可以通过launch函数开启一个协程

GlobalScope.launch(Dispatchers.IO) {

var result: WanResponse?=null

result = repository.login(userName,userPassword).await()

launch(Dispatchers.Main) {

btnLogin.text = result.data.username

}

}

这段代码出现了Dispatchers 调度器,它可以将协程限制在一个特定的线程执行,或者将它分派到一个线程池,或者让它不受限制地运行,关于 Dispatchers 这里先不展开了。

常用的 Dispatchers ,有以下三种:

  • Dispatchers.Main:Android 中的主线程
  • Dispatchers.IO:针对磁盘和网络 IO 进行了优化,适合 IO 密集型的任务,比如:读写文件,操作数据库以及网络请求
  • Dispatchers.Default:适合 CPU 密集型的任务,比如计算

但上面的栗子只是一次网络请求,如果有多次请求可能就变成这个样子:

GlobalScope.launch(Dispachers.IO) {

//io操作

launch(Dispachers.Main){

//ui操作

launch(Dispachers.IO) {

//io操作

launch(Dispacher.Main) {

//ui操作

}

}

}

}

这个嵌套???不是说协程可以不用写嵌套代码的吗

于是协程中有一个很实用的函数:withContext这个函数可以切换到指定的线程,并在闭包内的逻辑执行结束之后,自动把线程切回去继续执行,

用 withContext 改写一下,它的结构大致就长这个亚子:

launch(Dispachers.Main) {

withContext(Dispachers.IO) {

}

withContext(Dispachers.IO) {

}

}

复制代码

比如上面的登录的栗子就可以改写成这样:

GlobalScope.launch(Dispatchers.Main) {

var result: WanResponse?=null

withContext(Dispatchers.IO){

//请求登录

result = repository.login(userName,userPassword).await()

}

//更新ui

btnLogin.text = result?.data?.username

}

好像的确变得简洁了许多,但离我们的目标:看起来同步的方式写出异步的代码还差那么一点。

既然不需要嵌套了,那就可以把io线程的操作,拿出来单独作为函数,就可以写成这样:

suspend fun login(name: String,password: String): WanResponse {

return withContext(Dispatchers.IO) {

val repository = ApiRepository()

repository.login(name, password).await()

}

}

这个函数和普通函数不一样,多出来一个关键字suspend,直译过来是挂起的意思,那这个关键字真正的作用到底什么呢?这个下面会详细解释,这里先跳过。

挂起函数写好了,那开启协程部分的代码就可以改写一下

GlobalScope.launch (Dispatchers.Main){

val result =login(userName,userPassword)

btnLogin.text = result.data.username

}

这样看起来就和同步方式的代码一样了

supspend 关键字的作用

上面提到了挂起函数中的suspend,那它的作用是什么呢?是挂起作用?

如果是挂起作用,那它挂起的对象是什么?是当前线程还是所在的函数?

答案是都不是,协程中的挂起,本质上挂起的对象是协程。协程是啥?就是launch函数包起来的代码块。

GlobalScope.launch (Dispatchers.Main){

//login是个suspend函数

val result = login(userName,userPassword)

btnLogin.text = result.data.username

}

//Next

suspend fun login(name: String,password: String): WanResponse {

return withContext(Dispatchers.IO) {

val repository = ApiRepository()

repository.login(name, password).await()

}

}

当执行到suspend函数的时候,该协程就会在当前线程中被挂起,通俗一点理解,当前线程暂时不管这个协程了。

那当前线程它去做什么呢?它该去做啥就做啥,比如还是上面的例子,由于该协程是在主线程中的,在请求登录时协程就会被挂起,主线程就从这个协程中脱离出来,继续走NEXT之后的代码。当登录请求成功之后,挂起函数又会将其切换到主线程中。

敲黑板,敲黑板啦

挂起其实做的就是稍后会将线程自动切换回来的操作,切换回来的动作就叫恢复(resume),它是协程里的功能,所以我们要在协程里面(这个协程当然也可以是一个挂起函数),去调用自带的挂起函数,比如常用的withContext()

到这里你很可能就认为suspend关键字的作用就是挂起协程的作用了,那就太高估它,它并没有这么神奇的功能。

最后

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

以下是今天给大家分享的一些独家干货:

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究**。

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

以下是今天给大家分享的一些独家干货:

[外链图片转存中…(img-z4Eb7lhP-1715576337575)]

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值