Android ViewModelScope怎么自动取消协程(android,ViewModelScope,开发技术)

时间:2024-05-09 21:17:18 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

先看一下ViewModel中的ViewModelScope是何方神圣

valViewModel.viewModelScope:CoroutineScopeget(){valscope:CoroutineScope?=this.getTag(JOB_KEY)if(scope!=null){returnscope}returnsetTagIfAbsent(JOB_KEY,CloseableCoroutineScope(SupervisorJob()+Dispatchers.Main.immediate))}

可以看到这个是一个扩展方法,

再点击setTagIfAbsent方法进去

<T>TsetTagIfAbsent(Stringkey,TnewValue){Tprevious;synchronized(mBagOfTags){previous=(T)mBagOfTags.get(key);//第一次肯定为nullif(previous==null){mBagOfTags.put(key,newValue);//null存储}}Tresult=previous==null?newValue:previous;if(mCleared){//判断是否已经clear了//Itispossiblethatwe'llcallclose()multipletimesonthesameobject,but//Closeableinterfacerequiresclosemethodtobeidempotent://"ifthestreamisalreadyclosedtheninvokingthismethodhasnoeffect."(c)closeWithRuntimeException(result);}returnresult;}

可以看到 这边 会把 我们的 ViewModel 存储到 ViewModel 内的 mBagOfTags 中

这个 mBagOfTags 是

privatefinalMap<String,Object>mBagOfTags=newHashMap<>();

这个时候 我们 viewModel 就会持有 我们 viewModelScope 的协程 作用域了。那..这也只是 表述了 我们 viewModelScope 存在哪里而已,什么时候清除呢?

先看一下 ViewModel 的生命周期:

Android ViewModelScope怎么自动取消协程

可以看到 ViewModel 的生命周期 会在 Activity onDestory 之后会被调用。那...具体哪里调的?

翻看源码可以追溯到ComponentActivity的默认构造器内

publicComponentActivity(){/*省略一些*/getLifecycle().addObserver(newLifecycleEventObserver(){@OverridepublicvoidonStateChanged(@NonNullLifecycleOwnersource,@NonNullLifecycle.Eventevent){if(event==Lifecycle.Event.ON_DESTROY){if(!isChangingConfigurations()){getViewModelStore().clear();}}}});}

可以看到内部会通对 Lifecycle 添加一个观察者,观察当前 Activity 的生命周期变更事件,如果走到了 Destory ,并且 本次 Destory 并非由于配置变更引起的,才会真正调用 ViewModelStore 的 clear 方法。

跟进 clear 方法看看:

publicclassViewModelStore{privatefinalHashMap<String,ViewModel>mMap=newHashMap<>();/***ClearsinternalstorageandnotifiesViewModelsthattheyarenolongerused.*/publicfinalvoidclear(){for(ViewModelvm:mMap.values()){vm.clear();}mMap.clear();}}

可以看到这个 ViewModelStore 内部实现 用 HashMap 存储 ViewModel

于是在 clear 的时候,会逐个遍历调用 clear方法,再次跟进 ViewModel 的 clear 方法

@MainThreadfinalvoidclear(){mCleared=true;//Sinceclear()isfinal,thismethodisstillcalledonmockobjects//andinthosecases,mBagOfTagsisnull.It'llalwaysbeemptythough//becausesetTagIfAbsentandgetTagarenotfinalsowecanskip//clearingitif(mBagOfTags!=null){synchronized(mBagOfTags){for(Objectvalue:mBagOfTags.values()){//seecommentforthesimilarcallinsetTagIfAbsentcloseWithRuntimeException(value);}}}onCleared();}

可以发现我们最初 存放 viewmodelScope 的 mBagOfTags

这里面的逻辑 就是对 mBagOfTags 存储的数据 挨个提取出来并且调用 closeWithRuntimeException

跟进 closeWithRuntimeException:

privatestaticvoidcloseWithRuntimeException(Objectobj){if(objinstanceofCloseable){try{((Closeable)obj).close();}catch(IOExceptione){thrownewRuntimeException(e);}}}

该方法内会逐个判断 对象是否实现 Closeable 如果实现就会调用这个接口的 close 方法,

再回到最初 我们 viewModel 的扩展方法那边,看看我们 viewModelScope 的真正面目

internalclassCloseableCoroutineScope(context:CoroutineContext):Closeable,CoroutineScope{overridevalcoroutineContext:CoroutineContext=contextoverridefunclose(){coroutineContext.cancel()}}

可以明确的看到 我们的 ViewModelScope 实现了 Closeable 并且充写了 close 方法,

close 方法内的实现 会对 协程上下文进行 cancel。

至此我们 可以大致整理一下:

  • viewModelScope 是 ViewModel 的扩展成员,该对象是 CloseableCoroutineScope,并且实现了 Closeable 接口

  • ViewModelScope 存储在 ViewModel 的 名叫mBagOfTags的HashMap中 啊

  • ViewModel 存储在 Activity 的 ViewModelStore 中,并且会监听 Activity 的 Lifecycle 的状态变更,在ON_DESTROY 且 非配置变更引起的事件中 对 viewModelStore 进行清空

  • ViewModelStore 清空会对 ViewModelStore 内的所有 ViewModel 逐个调用 clear 方法。

  • ViewModel的clear方法会对 ViewModel的 mBagOfTags 内存储的对象进行调用 close 方法(该对象需实现Closeable 接口)

  • 最终会会调用 我们 ViewModelScope 的实现类 CloseableCoroutineScope 的 close 方法中。close 方法会对协程进行 cancel。

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:Android ViewModelScope怎么自动取消协程的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:javascript如何实现表单隔行变色下一篇:

9 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18