[英]Handle cancelation inside Kotlin Coroutines producer
是否有可能在生產者構建器本身內處理生產者取消? 取消訂閱回調可能很有用:
private fun changes(key: String) = produce<Unit>(UI, CONFLATED) {
val listener = OnSharedPreferenceChangeListener { _, changedKey ->
if (key == changedKey) offer(Unit)
}
prefs.registerOnSharedPreferenceChangeListener(listener)
???.onCancel {
prefs.unregisterOnSharedPreferenceChangeListener(listener)
}
}
或者可能存在實現這種情況的另一種方式?
首先,您不應該使用produce
構建器以這種方式使API與偵聽器一致,因為在produce
構建器主體存在時,通道立即關閉並且將停止服務其功能。 相反,您應該只創建一個Channel()
並創建相應的連接。
不幸的是,頻道目前不提供安裝取消偵聽器的開箱即用方式(參見問題#341 )。 在通道關閉時立即獲得通知的唯一方法是擴展相應的通道類,這將導致以下代碼:
private fun changes(key: String): ReceiveChannel<Unit> = object : ConflatedChannel<Unit>() {
val listener = OnSharedPreferenceChangeListener { _, changedKey ->
if (key == changedKey) offer(Unit)
}
init {
prefs.registerOnSharedPreferenceChangeListener(listener)
}
override fun afterClose(cause: Throwable?) {
prefs.unregisterOnSharedPreferenceChangeListener(listener)
}
}
即將推出的kotlinx.coroutines庫版本應公開 Channel.invokeOnClose Channel.invokeOnClose { ... }
方法以滿足此類用例。
但是,有解決方案同時具有此行為。 正如Roman Elizarov建議的那樣,一種解決方案是將您正在尋找的頻道子類化。
另一種解決方案是使用以下方式生產:
fun SharedPreferences.changes(key: String) = produce {
val changesChannel = ConflatedChannel<Unit>()
val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, changedKey ->
if (key == changedKey) changesChannel.offer(Unit)
}
registerOnSharedPreferenceChangeListener(listener)
try {
for (change in changesChannel) {
send(change)
}
} finally {
unregisterOnSharedPreferenceChangeListener(listener)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.