观看Sean's explanation on Android (Google I/O'19)后,我尝试了相同的方法:
init{
viewModelScope.launch {
Timber.i("coroutine awake")
while (true){
delay(2_000)
Timber.i("another round trip")
}
}
}
[不幸的是,onCleared
是在活动被杀死时调用的,但当它置于后台时才被调用(“当我们离开Activity ...时,背景正在“移开” imho ^^)。我得到以下输出:
> ---- Activity in Foreground
> 12:41:10.195 TEST: coroutine awake
> 12:41:12.215 TEST: another round trip
> 12:41:14.231 TEST: another round trip
> 12:41:16.245 TEST: another round trip
> 12:41:18.259 TEST: another round trip
> 12:41:20.270 TEST: another round trip
> ----- Activity in Background (on onCleared not fired)
> 12:41:22.283 TEST: another round trip
> 12:41:24.303 TEST: another round trip
> 12:41:26.320 TEST: another round trip
> 12:41:28.353 TEST: another round trip
> 12:41:30.361 TEST: another round trip
> ----- Activity in Foreground
> 12:41:30.369 TEST: coroutine awake
我该如何解决?
1-将代码从init
移到suspend fun start()
内部活动所调用的lifecycleScope.launchWhenStarted
吗?
我得到相同的结果。我以为lifecycleScope
进入背景时会取消其子协程,但是通过这种方法我得到了相同的Timber输出。
2-将我的ViewModel代码更改为:
private lateinit var job: Job
suspend fun startEmitting() {
job = viewModelScope.launch {
Timber.i("coroutine awake")
while (true){
delay(2_000)
Timber.i("another round trip")
}
}
}
fun cancelJob(){
if(job.isActive){
job.cancel()
}
}
而且,在我的活动中:
override fun onResume() {
super.onResume()
lifecycleScope.launch {
viewModel.startEmitting()
}
}
override fun onPause() {
super.onPause()
viewModel.cancelJob()
}
它很好,但是viewModelScope
不是为我管理CoroutineScope
的目的吗?我讨厌这个cancelJob逻辑。
解决此问题的最佳方法是什么?
Kotlin无法为您取消无限操作。您需要在某处致电isActive
。例如:while(isActive)
。