如何用 Flow 替换 LiveData

How to replace LiveData with Flow

我有一个名为 sortOrderLiveData,然后我有另一个名为 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")
        }
    }
}

问题

如果您无法将映射的冷流转换为热流,它会在您每次收集它时重新启动流(就像您的 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)

或者您可以创建一个单独的函数,在 mapstateIn 函数调用中调用。

    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。我有偏见,不过。

参见an article on medium