ViewModelScope 协程取消

背景:

在ViewModel中有个协程方法(viewModelScope),里面是whlie(true),始终进行网络查询。
该方法由fragment中的onResume调用

现象:

发现在viewmodel结束后,该协程依旧不停止。(原因有待确认)

过程:

  1. 改进为while(flag),在viewmodel中,重写onCleared()方法,将flag置为false。
    此方法仅在viewmodel生命周期结束后才有效。即对应的 fragment / activity onDestroy 之后才有效。如果是OnReusme()的时候,则无效。
fun getLocation(devId: String) {
        locationJob = viewModelScope.launch(Dispatchers.IO) {
            while (flag) {
                //do something
                Thread.sleep(GET_LOCATION_DURATION_TIME)
            }
        }
    }

override fun onCleared() {
        super.onCleared()
        Log.d(TAG, "MapViewModel onDestroy ")
        flag = false
    }
  1. 将ViewModel绑定LifeCycler,在onPause的时候,把flag置为false。
    发现该方法在APP快速切入切出的时候,会产生多次构造协程体,导致同时产生多个协程执行。这无疑是错误的。(怀疑是sleep没执行完,故协程未执行完,导致旧的协程未取消,新的协程就进来了,此时公用一个flag,旧的协程就继续执行下去了,未能被取消)
fun getLocation(devId: String) {
       locationJob = viewModelScope.launch(Dispatchers.IO) {
           while (flag) {
               //do something
               Thread.sleep(GET_LOCATION_DURATION_TIME)
           }
       }
   }

   @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
   fun onPause() {
        flag = false
   }
  1. 将ViewModel绑定LifeCycler,在onPause的时候,把协程cancel()掉。while循环通过协程的isActive状态判断。
       fun getLocation(devId: String) {
       locationJob = viewModelScope.launch(Dispatchers.IO) {
           Log.d(TAG, "getLocation >>>  is active : $isActive")			//  3. true
           while (isActive) {
               // todo something
               }
               Thread.sleep(GET_LOCATION_DURATION_TIME)
           }
       }

       @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
       fun onPause() {
           locationJob?.cancel()
           Log.d(TAG, "onPause  >>  is active :${locationJob?.isActive}")	//  1. true
       }
       
       @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
       fun onResume(){
           Log.d(TAG, "onPause  >>  is active :${locationJob?.isActive}")	//  2. true
       }

这个方法达到了最终目的,即无论是viewmodel onCleared() 还是 fragment onPause(),都可以保证只有一个协程在运行。

问题

目的虽然达到了,但是是试出来的。留下的疑问是为什么 在onResume()的时候,协程的状态被恢复了(即 log 2)。job.cancel()是否真正取消了协程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值