Saya dapat mengamati LiveData dari beberapa Fragmen. Bisakah saya melakukan ini dengan Flow? Jika ya lalu bagaimana?
Iya. Anda dapat melakukan ini dengan emit
dan collect
. Berpikir emit
mirip dengan data langsung postValue
dan collect
mirip dengan observe
. Mari kita beri contoh.
Gudang
// 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()
}
Pecahan
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
}
}
}
Kami dapat memiliki beberapa LiveData dari satu LiveData menggunakan peta & switchMap. Apakah ada cara untuk memiliki beberapa aliran dari satu sumber sumber?
Flow sangat berguna. Anda bisa membuat aliran di dalam aliran. Katakanlah Anda ingin menambahkan tanda derajat ke setiap data ramalan cuaca.
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)
}
}
}
Kemudian kumpulkan data dalam Fragmen sama dengan # 1. Di sini yang terjadi adalah model tampilan mengumpulkan data dari repositori dan fragmen mengumpulkan data dari model tampilan.
Menggunakan MutableLiveData saya dapat memperbarui data dari mana saja menggunakan referensi variabel. Apakah ada cara untuk melakukan hal yang sama dengan Flow?
Anda tidak dapat memancarkan nilai di luar aliran. Blok kode di dalam aliran hanya dieksekusi ketika ada kolektor. Tetapi Anda dapat mengonversi aliran ke data langsung dengan menggunakan ekstensi asLiveData dari LiveData.
ViewModel
fun getWeatherForecast(): LiveData<String> {
return forecastRepository
.getWeatherForecastEveryTwoSeconds()
.asLiveData() // Convert flow to live data
}
Dalam kasus Anda, Anda bisa melakukan ini
private fun getSharedPrefFlow() = callbackFlow {
val sharedPref = context?.getSharedPreferences("SHARED_PREF_NAME", MODE_PRIVATE)
sharedPref?.all?.forEach {
offer(it)
}
}
getSharedPrefFlow().collect {
val key = it.key
val value = it.value
}
Edit
Terima kasih kepada @mark atas komentarnya. Membuat aliran baru dalam model tampilan untuk getWeatherForecast
fungsi sebenarnya tidak perlu. Itu dapat ditulis ulang sebagai
fun getWeatherForecast(): Flow<String> {
return forecastRepository
.getWeatherForecastEveryTwoSeconds(spendingDetailsRequest)
.map {
it + " °C"
}
}