如何用 Flow 替换 LiveData
How to replace LiveData with Flow
我有一个名为 sortOrder
的 LiveData
,然后我有另一个名为 myData
的变量,它观察 sortOrder
的任何变化并相应地填充数据。
class TestViewModel @ViewModelInject constructor() : ViewModel() {
private val sortOrder = MutableLiveData<String>()
val myData = sortOrder.map {
Timber.d("Sort order changed to $it")
"Sort order is $it"
}
init {
sortOrder.value = "year"
}
}
观察 Activity
class TestActivity : AppCompatActivity() {
private val viewModel: TestViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
// Observing data
viewModel.myData.observe(this) {
Timber.d("Data is : $it")
}
}
}
问题
- 如何在不改变输出的情况下用
Flow/StateFlow
API 替换上述场景?
如果您无法将映射的冷流转换为热流,它会在您每次收集它时重新启动流(就像您的 Activity 被重新创建时一样)。这就是冷流的工作原理。
我感觉他们会充实 StateFlow/SharedFlow 的转换函数,因为将它们映射到冷流并不得不将它们转回热流感觉很尴尬。
如果您不想手动明确映射第一个元素,public Flow 必须是 SharedFlow,因为 stateIn
函数需要您直接提供初始状态。
private val sortOrder = MutableStateFlow("year")
val myData = sortOrder.map {
Timber.d("Sort order changed to $it")
"Sort order is $it"
}.shareIn(viewModelScope, SharingStarted.Eagerly, 1)
或者您可以创建一个单独的函数,在 map
和 stateIn
函数调用中调用。
private val sortOrder = MutableSharedFlow<String>()
private fun convertSortOrder(order: String): String {
Log.d("ViewModel", "Sort order changed to $order")
return "Sort order is $order"
}
val myData = sortOrder.map {
convertSortOrder(it)
}.stateIn(viewModelScope, SharingStarted.Eagerly, convertSortOrder("year"))
从fragment/activity开始,你必须在onStart()
创建一个收集流量的作业,并在onStop()
取消它。使用 lifecycleScope.launchWhenStarted
将保持流 活动 即使在后台也是如此。
使用 bindin 库轻松迁移到 Flow
。我有偏见,不过。
我有一个名为 sortOrder
的 LiveData
,然后我有另一个名为 myData
的变量,它观察 sortOrder
的任何变化并相应地填充数据。
class TestViewModel @ViewModelInject constructor() : ViewModel() {
private val sortOrder = MutableLiveData<String>()
val myData = sortOrder.map {
Timber.d("Sort order changed to $it")
"Sort order is $it"
}
init {
sortOrder.value = "year"
}
}
观察 Activity
class TestActivity : AppCompatActivity() {
private val viewModel: TestViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
// Observing data
viewModel.myData.observe(this) {
Timber.d("Data is : $it")
}
}
}
问题
- 如何在不改变输出的情况下用
Flow/StateFlow
API 替换上述场景?
如果您无法将映射的冷流转换为热流,它会在您每次收集它时重新启动流(就像您的 Activity 被重新创建时一样)。这就是冷流的工作原理。
我感觉他们会充实 StateFlow/SharedFlow 的转换函数,因为将它们映射到冷流并不得不将它们转回热流感觉很尴尬。
如果您不想手动明确映射第一个元素,public Flow 必须是 SharedFlow,因为 stateIn
函数需要您直接提供初始状态。
private val sortOrder = MutableStateFlow("year")
val myData = sortOrder.map {
Timber.d("Sort order changed to $it")
"Sort order is $it"
}.shareIn(viewModelScope, SharingStarted.Eagerly, 1)
或者您可以创建一个单独的函数,在 map
和 stateIn
函数调用中调用。
private val sortOrder = MutableSharedFlow<String>()
private fun convertSortOrder(order: String): String {
Log.d("ViewModel", "Sort order changed to $order")
return "Sort order is $order"
}
val myData = sortOrder.map {
convertSortOrder(it)
}.stateIn(viewModelScope, SharingStarted.Eagerly, convertSortOrder("year"))
从fragment/activity开始,你必须在onStart()
创建一个收集流量的作业,并在onStop()
取消它。使用 lifecycleScope.launchWhenStarted
将保持流 活动 即使在后台也是如此。
使用 bindin 库轻松迁移到 Flow
。我有偏见,不过。