产生背景
为了解决异步线程产生的回调地狱
//传统回调方式
api.login(phone,psd).enquene(new Callback<User>(){
public void onSuccess(User user){
api.submitAddress(address).enquene(new Callback<Result>(){
public void onSuccess(Result result){
...
}
});
}
});
//使用协程后
val user=api.login(phone,psd)
api.submitAddress(address)
...
协程是什么
本质上,协程是轻量级的线程。
协程关键名词
val job = GlobalScope.launch {
delay(1000)
println("World World!")
}
-
CoroutineScope(作用范围)
控制协程代码块执行的线程,生命周期等,包括GlobeScope、lifecycleScope、viewModelScope以及其他自定义的CoroutineScope
GlobeScope:全局范围,不会自动结束执行
lifecycleScope:生命周期范围,用于activity等有生命周期的组件,在DESTROYED的时候会自动结束,需额外引入
viewModelScope:viewModel范围,用于ViewModel中,在ViewModel被回收时会自动结束,需额外引入
-
Job(作业)
协程的计量单位,相当于一次工作任务,launch方法默认返回一个新的Job
-
suspend(挂起)
作用于方法上,代表该方法是耗时任务,例如上面的delay方法
public suspend fun delay(timeMillis: Long) {
...
}
协程的引入
主框架($coroutines_version替换为最新版本,如1.3.9,下同)
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
lifecycleScope(可选,版本2.2.0)
implementation 'androidx.activity:activity-ktx:$lifecycle_scope_version'
viewModelScope(可选,版本2.3.0-beta01)
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$coroutines_viewmodel_version"
简单使用
先举个简单例子
lifecycleScope.launch {
delay(2000)
tvTest.text="Test"
}
上面这个例子实现的功能是等待2秒,然后修改id为tvTest的TextView控件的text值为Test
自定义延迟返回方法
在kotlin里面,对于需要延迟才能返回结果的方法,需要用suspend标明
lifecycleScope.launch {
val text=getText()
tvTest.text = text
}
suspend fun getText():String{
delay(2000)
return "getText"
}
如果在其他线程,需要使用Continuation进行线程切换,可使用suspendCancellableCoroutine 或 suspendCoroutine包裹(前者可取消,相当于后者的扩展),成功调用it.resume(),失败调用it.resumeWithException(Exception()),抛出异常
suspend fun getTextInOtherThread() = suspendCancellableCoroutine<String> {
thread {
Thread.sleep(2000)
it.resume("getText")
}
}
异常捕获
协程里面的失败都可以通过异常捕获,来统一处理特殊情况
lifecycleScope.launch {
try {
val text=getText()
tvTest.text = text
} catch (e:Exception){
e.printSt