網(wǎng)站首頁 編程語言 正文
先看一下?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))
}
可以看到這個(gè)是一個(gè)擴(kuò)展方法,
再點(diǎn)擊?setTagIfAbsent?方法進(jìn)去
<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 存儲(chǔ)
}
}
T result = previous == null ? newValue : previous;
if (mCleared) {//判斷是否已經(jīng)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;
}
可以看到 這邊 會(huì)把 我們的 ViewModel 存儲(chǔ)到 ViewModel 內(nèi)的 mBagOfTags 中
這個(gè) mBagOfTags 是
private final Map<String, Object> mBagOfTags = new HashMap<>();
這個(gè)時(shí)候 我們 viewModel 就會(huì)持有 我們 viewModelScope 的協(xié)程 作用域了。那..這也只是 表述了 我們 viewModelScope 存在哪里而已,什么時(shí)候清除呢?
先看一下 ViewModel 的生命周期:
可以看到 ViewModel 的生命周期 會(huì)在 Activity onDestory 之后會(huì)被調(diào)用。那...具體哪里調(diào)的?
翻看源碼可以追溯到?ComponentActivity?的默認(rèn)構(gòu)造器內(nèi)
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();
}
}
}
});
}
可以看到內(nèi)部會(huì)通對(duì) Lifecycle 添加一個(gè)觀察者,觀察當(dāng)前 Activity 的生命周期變更事件,如果走到了 Destory ,并且 本次 Destory 并非由于配置變更引起的,才會(huì)真正調(diào)用 ViewModelStore 的 clear 方法。
跟進(jìn) 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();
}
}
可以看到這個(gè) ViewModelStore 內(nèi)部實(shí)現(xiàn) 用 HashMap 存儲(chǔ) ViewModel
于是在 clear 的時(shí)候,會(huì)逐個(gè)遍歷調(diào)用 clear方法,再次跟進(jìn) 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();
}
可以發(fā)現(xiàn)我們最初 存放 viewmodelScope 的 mBagOfTags
這里面的邏輯 就是對(duì) mBagOfTags 存儲(chǔ)的數(shù)據(jù) 挨個(gè)提取出來并且調(diào)用 closeWithRuntimeException
跟進(jìn) closeWithRuntimeException:
private static void closeWithRuntimeException(Object obj) {
if (obj instanceof Closeable) {
try {
((Closeable) obj).close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
該方法內(nèi)會(huì)逐個(gè)判斷 對(duì)象是否實(shí)現(xiàn) Closeable 如果實(shí)現(xiàn)就會(huì)調(diào)用這個(gè)接口的 close 方法,
再回到最初 我們 viewModel 的擴(kuò)展方法那邊,看看我們 viewModelScope 的真正面目
internal class CloseableCoroutineScope(context: CoroutineContext)
: Closeable, CoroutineScope {
override val coroutineContext: CoroutineContext = context
override fun close() {
coroutineContext.cancel()
}
}
可以明確的看到 我們的 ViewModelScope 實(shí)現(xiàn)了 Closeable 并且充寫了 close 方法,
close 方法內(nèi)的實(shí)現(xiàn) 會(huì)對(duì) 協(xié)程上下文進(jìn)行 cancel。
至此我們 可以大致整理一下:
- viewModelScope 是 ViewModel 的擴(kuò)展成員,該對(duì)象是 CloseableCoroutineScope,并且實(shí)現(xiàn)了 Closeable 接口
- ViewModelScope 存儲(chǔ)在 ViewModel 的 名叫?mBagOfTags?的HashMap中 啊
- ViewModel 存儲(chǔ)在 Activity 的 ViewModelStore 中,并且會(huì)監(jiān)聽 Activity 的 Lifecycle 的狀態(tài)變更,在ON_DESTROY 且 非配置變更引起的事件中 對(duì) viewModelStore 進(jìn)行清空
- ViewModelStore 清空會(huì)對(duì) ViewModelStore 內(nèi)的所有 ViewModel 逐個(gè)調(diào)用 clear 方法。
- ViewModel的clear方法會(huì)對(duì) ViewModel的 mBagOfTags 內(nèi)存儲(chǔ)的對(duì)象進(jìn)行調(diào)用 close 方法(該對(duì)象需實(shí)現(xiàn)Closeable 接口)
- 最終會(huì)會(huì)調(diào)用 我們 ViewModelScope 的實(shí)現(xiàn)類 CloseableCoroutineScope 的 close 方法中。close 方法會(huì)對(duì)協(xié)程進(jìn)行 cancel。
原文鏈接:https://juejin.cn/post/7115406929165287438
相關(guān)推薦
- 2022-05-20 Modscan和Modsim 兩種Modbus調(diào)試工具使用說明
- 2022-08-01 使用docker環(huán)境變量動(dòng)態(tài)配置nginx的問題小結(jié)_docker
- 2022-09-09 C#表達(dá)式和運(yùn)算符詳細(xì)解析_C#教程
- 2022-07-13 SpringCloud之http客戶端Feign
- 2022-11-02 React組件實(shí)例三大屬性state?props?refs使用詳解_React
- 2023-07-03 CSS 中有五種常見的定位方式--詳解
- 2022-08-20 windows系統(tǒng)安裝配置nginx環(huán)境_nginx
- 2022-07-16 from .cv2 import * 沒有這個(gè)模塊
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支