Tengo un código que debería cambiar SharedPreferences en almacenamiento observable con flujo, así que tengo un código como este
internal val onKeyValueChange: Flow<String> = channelFlow { val callback = SharedPreferences.OnSharedPreferenceChangeListener { _, key -> coroutineScope.launch { //send(key) offer(key) } } sharedPreferences.registerOnSharedPreferenceChangeListener(callback) awaitClose { sharedPreferences.unregisterOnSharedPreferenceChangeListener(callback) } }o esto
internal val onKeyValueChange: Flow<String> = callbackFlow { val callback = SharedPreferences.OnSharedPreferenceChangeListener { _, key -> coroutineScope.launch { send(key) //offer(key) } } sharedPreferences.registerOnSharedPreferenceChangeListener(callback) awaitClose { sharedPreferences.unregisterOnSharedPreferenceChangeListener(callback) } }Luego observo estas preferencias para token, ID de usuario, ID de empresa y luego inicio sesión, pero hay algo extraño, ya que necesito crear la aplicación tres veces, como cambiar el token, no hace que tokenFlow emita nada, luego, la segunda vez, el nuevo ID de usuario no hace que userIdFlow emita nada, luego, después del tercer inicio de sesión, puedo cerrar sesión/iniciar sesión y funciona. Al cerrar la sesión, estoy borrando las 3 tiendas de propiedades en el token de preferencias, ID de usuario, ID de empresa.
Para callbackFlow :
No puede usar emit() como el Flow simple (porque es una función de suspend ) dentro de una devolución de llamada. Por lo tanto, callbackFlow le ofrece una forma sincronizada de hacerlo con la opción trySend() .
Ejemplo:
fun observeData() = flow { myAwesomeInterface.addListener{ result -> emit(result) // NOT ALLOWED } } Entonces, las rutinas le ofrecen la opción de callbackFlow :
fun observeData() = callbackFlow { myAwesomeInterface.addListener{ result -> trySend(result) // ALLOWED } awaitClose{ myAwesomeInterface.removeListener() } } Para channelFlow :
La principal diferencia con él y el Flow básico se describe en la documentación :
Se utiliza un canal con el tamaño de búfer predeterminado. Utilice el operador de búfer en el flujo resultante para especificar un valor definido por el usuario y para controlar lo que sucede cuando los datos se producen más rápido de lo que se consumen, es decir, para controlar el comportamiento de la contrapresión.
trySend() sigue representando lo mismo. Es solo una forma sincronizada (una forma no suspending ) para emit() o send()
Le sugiero que consulte el blog de Romans Elizarov para obtener información más detallada, especialmente esta publicación.
Con respecto a su código, para callbackFlow no necesitará un lanzamiento de rutina:
coroutineScope.launch { send(key) //trySend(key) } Solo usa trySend()