[英]How to get coroutine scope in lower level manager class
我的一個庫中有一個數據管理器類。 到目前為止,它一直在與執行程序合作並擁有自己的執行程序。 現在該類正在轉換為協程。
當管理器必須異步初始化數據時會出現問題,如下例所示。 為了執行掛起函數,對suspendedInit
的調用必須包含在launch
。 這里的問題是管理器沒有自己的協程范圍。
有些我正在看但不喜歡:
DataManager
構造函數並使用它。 問題是DataManager
的用戶還不支持協程,因此沒有自己的范圍。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.