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之后的代码。当登录请求成功之后,挂起函数又会将其切换到主线程中。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
尾声
你不踏出去一步,永远不知道自己潜力有多大,千万别被这个社会套在我们身上的枷锁给捆住了,30岁我不怕,35岁我一样不怕,去做自己想做的事,为自己拼一把吧!不试试怎么知道你不行呢?
改变人生,没有什么捷径可言,这条路需要自己亲自去走一走,只有深入思考,不断反思总结,保持学习的热情,一步一步构建自己完整的知识体系,才是最终的制胜之道,也是程序员应该承担的使命。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
自己拼一把吧!不试试怎么知道你不行呢?
改变人生,没有什么捷径可言,这条路需要自己亲自去走一走,只有深入思考,不断反思总结,保持学习的热情,一步一步构建自己完整的知识体系,才是最终的制胜之道,也是程序员应该承担的使命。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中…(img-o6CsUBun-1712661902417)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!