先看一下 viewmodel 中的 viewmodelscope 是何方神圣
val viewmodel.viewmodelscope: coroutinescope
get() {
val scope: coroutinescope? = this.gettag(job_key)
if (scope != null) {
return scope
}
return settagifabsent(job_key,
closeablecoroutinescope(supervisorjob() + dispatchers.main.immediate))
}
可以看到这个是一个扩展方法,
再点击 settagifabsent 方法进去
<t> t settagifabsent(string key, t newvalue) {
t previous;
synchronized (mbagoftags) {
previous = (t) mbagoftags.get(key);//第一次肯定为null
if (previous == null) {
mbagoftags.put(key, newvalue);//null 存储
}
}
t result = previous == null ? newvalue : previous;
if (mcleared) {//判断是否已经clear了
// it is possible that we'll call close() multiple times on the same object, but
// closeable interface requires close method to be idempotent:
// "if the stream is already closed then invoking this method has no effect." (c)
closewithruntimeexception(result);
}
return result;
}
可以看到 这边 会把 我们的 viewmodel 存储到 viewmodel 内的 mbagoftags 中
这个 mbagoftags 是
private final map<string, object> mbagoftags = new hashmap<>();
这个时候 我们 viewmodel 就会持有 我们 viewmodelscope 的协程 作用域了。那..这也只是 表述了 我们 viewmodelscope 存在哪里而已,什么时候清除呢?
先看一下 viewmodel 的生命周期:
可以看到 viewmodel 的生命周期 会在 activity ondestory 之后会被调用。那…具体哪里调的?
翻看源码可以追溯到 componentactivity 的默认构造器内
public componentactivity() {
/*省略一些*/
getlifecycle().addobserver(new lifecycleeventobserver() {
@override
public void onstatechanged(@nonnull lifecycleowner source,
@nonnull lifecycle.event event) {
if (event == lifecycle.event.on_destroy) {
if (!ischangingconfigurations()) {
getviewmodelstore().clear();
}
}
}
});
}
可以看到内部会通对 lifecycle 添加一个观察者,观察当前 activity 的生命周期变更事件,如果走到了 destory ,并且 本次 destory 并非由于配置变更引起的,才会真正调用 viewmodelstore 的 clear 方法。
跟进 clear 方法看看:
public class viewmodelstore {
private final hashmap<string, viewmodel> mmap = new hashmap<>();
/**
* clears internal storage and notifies viewmodels that they are no longer used.
*/
public final void clear() {
for (viewmodel vm : mmap.values()) {
vm.clear();
}
mmap.clear();
}
}
可以看到这个 viewmodelstore 内部实现 用 hashmap 存储 viewmodel
于是在 clear 的时候,会逐个遍历调用 clear方法,再次跟进 viewmodel 的 clear 方法
@mainthread
final void clear() {
mcleared = true;
// since clear() is final, this method is still called on mock objects
// and in those cases, mbagoftags is null. it'll always be empty though
// because settagifabsent and gettag are not final so we can skip
// clearing it
if (mbagoftags != null) {
synchronized (mbagoftags) {
for (object value : mbagoftags.values()) {
// see comment for the similar call in settagifabsent
closewithruntimeexception(value);
}
}
}
oncleared();
}
可以发现我们最初 存放 viewmodelscope 的 mbagoftags
这里面的逻辑 就是对 mbagoftags 存储的数据 挨个提取出来并且调用 closewithruntimeexception
跟进 closewithruntimeexception:
private static void closewithruntimeexception(object obj) {
if (obj instanceof closeable) {
try {
((closeable) obj).close();
} catch (ioexception e) {
throw new runtimeexception(e);
}
}
}
该方法内会逐个判断 对象是否实现 closeable 如果实现就会调用这个接口的 close 方法,
再回到最初 我们 viewmodel 的扩展方法那边,看看我们 viewmodelscope 的真正面目
internal class closeablecoroutinescope(context: coroutinecontext)
: closeable, coroutinescope {
override val coroutinecontext: coroutinecontext = context
override fun close() {
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。
到此这篇关于一文了解android viewmodelscope 如何自动取消协程的文章就介绍到这了,更多相关android viewmodel scope 取消协程内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
