91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android?ViewModelScope怎么自動取消協程

發布時間:2022-07-04 09:37:57 來源:億速云 閱讀:158 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“Android ViewModelScope怎么自動取消協程”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Android ViewModelScope怎么自動取消協程”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

先看一下 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 的生命周期:

Android?ViewModelScope怎么自動取消協程

可以看到 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怎么自動取消協程”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

阿拉尔市| 安宁市| 息烽县| 铜陵市| 祁阳县| 龙山县| 安仁县| 二连浩特市| 扬中市| 鲁甸县| 浦江县| 襄汾县| 宣汉县| 云霄县| 新竹市| 湖州市| 舟曲县| 无锡市| 桂平市| 习水县| 泸水县| 东乌珠穆沁旗| 乌拉特中旗| 神木县| 孙吴县| 河池市| 德昌县| 梁河县| 永平县| 台江县| 聊城市| 定远县| 闽侯县| 阳城县| 道孚县| 同江市| 迭部县| 柳河县| 遂宁市| 辽中县| 诸暨市|