Android Kotlin协程:flow,callbackFlow,channelFlow等其他流构造函数之间有什么区别

时间:2020-05-18 08:46:01

标签: kotlin kotlin-coroutines kotlin-flow

我有一些代码,应该将SharedPreferences更改为带有流的可废弃存储,所以我有这样的代码

internal val onKeyValueChange: Flow<String> = channelFlow {
        val callback = SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
            coroutineScope.launch {
                //send(key)
                offer(key)
            }
        }

        sharedPreferences.registerOnSharedPreferenceChangeListener(callback)

        awaitClose {
            sharedPreferences.unregisterOnSharedPreferenceChangeListener(callback)
        }
    }

或这个

internal val onKeyValueChange: Flow<String> = callbackFlow {
        val callback = SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
            coroutineScope.launch {
                send(key)
                //offer(key)
            }
        }

        sharedPreferences.registerOnSharedPreferenceChangeListener(callback)

        awaitClose {
            sharedPreferences.unregisterOnSharedPreferenceChangeListener(callback)
        }
    }

然后,我观察到令牌,用户标识,公司标识的此首选项,然后登录,但是有些奇怪,因为我需要构建应用程序三遍,例如更改令牌不会导致令牌流发出任何东西,然后第二次新用户标识不会导致用户标识流发出任何东西,然后在第三次登录后,我可以注销/登录,并且可以正常工作。注销时,我将清除prefs令牌,userId,companyId中的所有3个属性存储。

1 个答案:

答案 0 :(得分:8)

对于callbackFlow

您不能在回调中将emit()用作简单的Flow(因为它是suspend函数)。因此,callbackFlow为您提供了一种使用offer()选项的同步方式。

示例:

fun observeData() = flow {
 myAwesomeInterface.addListener{ result ->
   emit(result) // NOT ALLOWED
 }
}

因此,协程为您提供了callbackFlow的选择:

fun observeData() = callbackFlow {
 myAwesomeInterface.addListener{ result ->
   offer(result) // ALLOWED
 }
 awaitClose{ myAwesomeInterface.removeListener() }
}

对于channelFlow

Flow基本的区别在于documentation

使用具有默认缓冲区大小的通道。使用缓冲区 运算符在结果流上指定用户定义的值并 控制数据生成速度快于消费速度时发生的情况,即 控制背压行为。

offer()仍然代表同一件事。这只是suspendingemit()

的同步方式(非send()方式)

我建议您检查Romans Elizarov blog以获得更详细的信息,尤其是this帖子。

关于您的代码,对于callbackFlow,您不需要协程启动:

coroutineScope.launch {
                send(key)
                //offer(key)
            }

只需使用offer()