Tôi có thể quan sát LiveData từ nhiều mảnh vỡ. Tôi có thể làm điều này với Flow không? Nếu có thì làm thế nào?
Đúng. Bạn có thể làm điều này với emit
và collect
. Suy nghĩ emit
tương tự như dữ liệu trực tiếp postValue
và collect
tương tự như observe
. Hãy cho một ví dụ.
Kho
// 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()
}
Miếng
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
}
}
}
Chúng tôi có thể có nhiều LiveData từ một LiveData bằng cách sử dụng map & switchMap. Có cách nào để có nhiều Flow từ một luồng nguồn không?
Dòng chảy rất tiện dụng. Bạn chỉ có thể tạo dòng chảy bên trong dòng chảy. Hãy nói rằng bạn muốn thêm ký hiệu độ vào từng dữ liệu dự báo thời tiết.
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)
}
}
}
Sau đó thu thập dữ liệu trong Fragment giống như # 1. Ở đây điều xảy ra là mô hình xem đang thu thập dữ liệu từ kho lưu trữ và đoạn đang thu thập dữ liệu từ mô hình xem.
Sử dụng MutableLiveData Tôi có thể cập nhật dữ liệu từ bất cứ đâu bằng cách sử dụng tham chiếu biến. Có cách nào để làm điều tương tự với Flow không?
Bạn không thể phát ra giá trị bên ngoài dòng chảy. Khối mã bên trong luồng chỉ được thực thi khi có bất kỳ trình thu thập nào. Nhưng bạn có thể chuyển đổi luồng thành dữ liệu trực tiếp bằng cách sử dụng tiện ích mở rộng asLiveData từ LiveData.
ViewModel
fun getWeatherForecast(): LiveData<String> {
return forecastRepository
.getWeatherForecastEveryTwoSeconds()
.asLiveData() // Convert flow to live data
}
Trong trường hợp của bạn, bạn có thể làm điều này
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
}
Biên tập
Cảm ơn @mark vì bình luận của anh ấy. Tạo một luồng mới trong mô hình khung nhìn cho getWeatherForecast
chức năng thực sự không cần thiết. Nó có thể được viết lại thành
fun getWeatherForecast(): Flow<String> {
return forecastRepository
.getWeatherForecastEveryTwoSeconds(spendingDetailsRequest)
.map {
it + " °C"
}
}