簡體   English   中英

在某些情況下(單例)可以在 Android 上從 Globalscope 啟動協程嗎?

[英]Is it OK to launch coroutines from Globalscope on Android in certain situations (singletons)?

當從活動、片段或 Android 架構組件視圖模型啟動協程時,使用綁定到該視圖組件生命周期的協程范圍是完全有意義的,以避免泄漏和釋放資源,例如在用戶離開時取消網絡請求屏幕。

但在其他情況下,即使用戶離開屏幕,您也不想取消協程,例如執行網絡請求進行分析或寫入數據庫時​​。 在這種情況下,可以使用GlobalScope啟動協程嗎? 啟動這些協程的對象大多是Singletons ,所以它們無論如何都會在應用程序的生命周期中存在,所以沒有泄漏的危險,對吧?

在 GlobalScope 上,Kotlin 文檔非常清楚:

應用程序代碼通常應該使用應用程序定義的 CoroutineScope。 強烈建議不要在 GlobalScope 實例上使用 async 或 launch。

在這些情況下可以使用 GlobalScope 嗎? 如果不是,我的應用程序定義的 CoroutineScope 應該是什么樣的?

如果您有一個生命周期真正全局化的異步工作線程(它們只會在您的進程終止時終止/終止),那么使用GlobalScope或類似的終身作用域就可以了。

假設您有一個發出請求的 Activity,但即使 Activity 消失,實際的網絡請求也需要繼續,因為您希望在網絡最終返回響應時緩存它。

您將CoroutineScope添加到您的 Activity/Fragment,或者更好地添加到您的 ViewModel,並讓您的代碼最終在該范圍內運行屏幕上的內容。 當 Activity/Fragment/ViewModel 死亡時,范圍將被取消,並且不會嘗試在不再存在的屏幕上顯示任何內容。

但是,您的 Fragment/Activity/ViewModel 可能會與具有生命周期的數據源/存儲庫對話,該生命周期僅在進程終止時結束。 您可以在那里切換到 GlobalScope,以便緩存您的網絡響應,即使沒有活動/片段/ViewModel 處於活動狀態以在屏幕上顯示結果。

class MyViewModel(context: CoroutineContext, repo: MyRepository) : ViewModel() {
    private val scope = CoroutineScope(context + SuperviserJob())

    override fun onCleared() { scope.cancel() }

    fun getDataFromNetwork() {
        scope.launch {
            myLiveData.value = repo.getDataFromNetwork()
        }
    }

}

// Singleton class
class MyRepositoryImpl(context: CoroutineContext) : MyRepository {
    private val scope = CoroutineScope(context + SupervisorJob())

    override suspend fun getDataFromNetwork() : String {
        return scope.async { // switch scopes
            val data = ... fetch data ...
            saveInCache(data)
        }.await()
    }
}

當您的 ViewModel 結束時( onCleared被調用), MyRepositoryImplgetDataFromNetwork仍然保持運行,如果一切順利,將調用saveInCache 但是,返回的值不會分配給myLiveData.value因為您的 ViewModel 范圍的協程被取消。

鑒於您已經嘗試將它附加到應用程序的生命周期,我建議要么將作用域傳遞給您的單例,要么通過它實現一個協程作用域。 不幸的是,在 GlobalScope 上運行協程仍然可能以泄漏告終。 有關更多信息,請參閱 Roman Elizarov 的這篇精彩文章: https : //medium.com/@elizarov/the-reason-to-avoid-globalscope-835337445abc

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM