Kotlin Flow vs Android LiveData

问题描述 投票:1回答:2

我对Kotlin Flow有疑问

  1. 我可以从多个片段观察LiveData。我可以用Flow做到这一点吗?如果是,那怎么办?
  2. 我们可以使用mapswitchMap从单个LiveData中获得多个LiveData。有没有办法从一个源流获得多个流?
  3. 使用MutableLiveData我可以使用变量引用从任何地方更新数据。有什么方法可以对Flow进行同样的操作?

我有一个用例,例如:我将使用SharedPreferences观察一个callbackFlow{...},这将给我一个源流。我想从该流中为每个键值对创建多个流。

这些听起来可能很愚蠢。我是Rx and Flow世界的新手。

android kotlin android-livedata kotlin-coroutines
2个回答
0
投票
  1. 当然可以。您可以使用launchIn(scope),onEach()等的组合在任意位置启动它。
  2. 存在大量的运算符/转换流程。自己写一个很容易-只需查看源代码并尝试:)
  3. [您可能可以通过例如私有广播频道,然后使用consumeAsFlow进行消费(如果我没记错的话)

对于您的用例,您可以这样做:

'''yourFlow.filter(...)-检查键值.onEach(...)-做你的神奇逻辑.launchIn(viewModelScope)-或任何地方'''抱歉,格式很糟糕,我是从电话写的。

希望这会有所帮助。干杯!


0
投票

我可以从多个片段观察LiveData。我可以用Flow做到这一点吗?如果是,那怎么办?

是。您可以使用emitcollect进行此操作。认为emit与实时数据postValue类似,并且collectobserve类似。让我们举个例子。

存储库

// I just faked the weather forecast
val weatherForecast = listOf("10", "12", "9")

// This function returns flow of forecast data
// Whenever the data is fetched, it is emitted so that
// collector can collect (if there is any)
fun getWeatherForecastEveryTwoSeconds(): Flow<String> = flow { 
    for (i in weatherForecast) {
        delay(2000)
        emit(i)
    }
}

ViewModel

fun getWeatherForecast(): Flow<String> {
    return forecastRepository.getWeatherForecastEveryTwoSeconds()
}

片段

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    // Collect is suspend function. So you have to call it from a 
    // coroutine scope. You can create a new coroutine or just use 
    // lifecycleScope
    // https://developer.android.com/topic/libraries/architecture/coroutines
    lifecycleScope.launch {
            viewModel.getWeatherForecastEveryTwoSeconds().collect {
                    // Use the weather forecast data
                    // This will be called 3 times since we have 3 
                    // weather forecast data
            }
    }
}

我们可以使用map&switchMap从单个LiveData中获得多个LiveData。有没有办法从一个源流获得多个流?

流程非常方便。您可以在流内部创建流。假设您要在每个天气预报数据后附加度号。

ViewModel

fun getWeatherForecast(): Flow<String> {
    return flow {
        forecastRepository
            .getWeatherForecastEveryTwoSeconds(spendingDetailsRequest)
                .map {
                    it + " °C"
                }
                .collect {
                    // This will send "10 °C", "12 °C" and "9 °C" respectively
                    emit(it) 
                }
    }
}

然后收集与#1相同的Fragment中的数据。这里发生的是视图模型正在从存储库收集数据,而片段是从视图模型收集数据。

使用MutableLiveData,我可以使用变量引用从任何地方更新数据。有什么方法可以对Flow进行同样的操作?

您不能在流程之外释放价值。内部流的代码块仅在有任何收集器时才执行。但是您可以使用LiveData的asLiveData扩展名将流转换为实时数据。

ViewModel

fun getWeatherForecast(): LiveData<String> {
    return forecastRepository
    .getWeatherForecastEveryTwoSeconds()
    .asLiveData() // Convert flow to live data
}

根据您的情况,您可以执行此操作

private fun getSharedPrefFlow() = callbackFlow {
    val sharedPref = context?.getSharedPreferences("SHERED_PREF_NAME", MODE_PRIVATE)
    sharedPref?.all?.forEach {
        offer(it)
    }
}

getSharedPrefFlow().collect {
    val key = it.key
    val value = it.value
}
© www.soinside.com 2019 - 2024. All rights reserved.