簡體   English   中英

如何在較低級別的管理器類中獲取協程范圍

[英]How to get coroutine scope in lower level manager class

我的一個庫中有一個數據管理器類。 到目前為止,它一直在與執行程序合作並擁有自己的執行程序。 現在該類正在轉換為協程。

當管理器必須異步初始化數據時會出現問題,如下例所示。 為了執行掛起函數,對suspendedInit的調用必須包含在launch 這里的問題是管理器沒有自己的協程范圍。

有些我正在看但不喜歡:

  1. 將協程范圍傳遞給DataManager構造函數並使用它。 問題是DataManager的用戶還不支持協程,因此沒有自己的范圍。
  2. DataManager實現CoroutineScope並創建自己的作用域。 正如CoroutineScope文檔所記錄的CoroutineScope不鼓勵這樣做。

這個問題的推薦解決方案是什么?

    class DataManager {
        init {
            suspendedInit()
        }
        
        private suspend fun suspendedInit() = withContext(Dispatchers.IO) {
            /* some long asynchronous operations here */
        }
    }

DataManager 實現 CoroutineScope 並創建自己的作用域。 正如 CoroutineScope 文檔所記錄的那樣,不鼓勵這樣做。

如果最初的DataManager有自己的 executor,它很可能也有自己的生命周期,並以適當的方式關閉該 executor。

在這種情況下,完全可以像創建執行程序一樣創建自己的CoroutineScope (實際上它可以從字面上基於您的初始執行程序)。 唯一不鼓勵的情況是如果您沒有正確處理范圍的生命周期:

CoroutineScope 應聲明為實體的屬性,該實體具有明確定義的生命周期,負責啟動子協程。

CustomScope 自定義使用的關鍵部分是取消它和生命周期的結束。 當不再需要啟動協程的實體時,應使用 CoroutineScope.cancel 擴展函數。

class DataManager {

    private val executor = TODO("original executor definition")
    val coroutineScope = executor.asCoroutineDispatcher()

    init {
        coroutineScope.launch {
            suspendedInit()
        }
    }

    private suspend fun suspendedInit() = ...

    fun close() {
        // executor.shutdown() // <-- not needed anymore
        coroutineScope.cancel()
    }
}

如果您不需要獨立的線程池,您也可以完全擺脫執行程序。 在這種情況下,您可以使用CoroutineScope(Dispatchers.IO) (如果您想要為所有協程使用 IO 調度程序)或CoroutineScope(Dispatchers.Default) (如果您打算啟動主要受 CPU 限制的任務)來初始化范圍並在必要時使用withContext(IO)

您可以向DataManager添加coroutineScope字段,如下所示:

private val coroutineScope = CoroutineScope(Dispatchers.IO)

然后從該范圍調用suspendedInit()

暫無
暫無

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

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