简体   繁体   English

如何用 Flow 替换 LiveData

[英]How to replace LiveData with Flow

I've one LiveData named sortOrder and then I've another variable named myData that observes any change to sortOrder and populates data accordingly.我有一个名为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"
    }

}

Observing in 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")
        }
    }
}

Question

  • How can I replace the above scenario with Flow/StateFlow APIs without any change in output?如何在 output 中没有任何变化的情况下用Flow/StateFlow API 替换上述场景?

If you fail to convert the mapped cold Flow into a hot Flow, it will restart the flow every time you collect it (like when your Activity is recreated).如果您无法将映射的冷流转换为热流,它会在您每次收集它时重新启动流(就像重新创建 Activity 时一样)。 That's how cold flows work.这就是冷流的工作原理。

I have a feeling they will flesh out the transform functions for StateFlow/SharedFlow, because it feels very awkward to map them to cold flows and have to turn them back into hot flows.我有一种感觉,他们会充实 StateFlow/SharedFlow 的转换函数,因为将它们转换为冷流并不得不将它们转回热流感觉非常尴尬。

The public Flow has to be a SharedFlow if you don't want to manually map the first element distinctly because the stateIn function requires you to directly provide an initial state.如果您不想手动 map 明确第一个元素,则公共 Flow 必须是 SharedFlow,因为stateIn function 要求您直接提供初始 state。

    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)

Or you could create a separate function that is called within map and also in a stateIn function call.或者您可以创建一个单独的 function,它在map中调用,也在stateIn function 调用中调用。

    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"))

I've one LiveData named sortOrder and then I've another variable named myData that observes any change to sortOrder and populates data accordingly.我有一个名为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"
    }

}

Observing in 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")
        }
    }
}

Question问题

  • How can I replace the above scenario with Flow/StateFlow APIs without any change in output?如何在不更改 output 的情况下用Flow/StateFlow API 替换上述场景?

From the point of the fragment/activity, you have to create a job that collects the flow in onStart() and cancel it in onStop() .从片段/活动的角度来看,您必须创建一个作业来收集onStart()中的流并在onStop()中取消它。 Using the lifecycleScope.launchWhenStarted will keep the flow active even in the background.使用lifecycleScope.launchWhenStarted将使流即使在后台也保持活动状态

Use the bindin library to migrate to Flow with ease.使用绑定库轻松迁移到Flow I'm biased, tho.我有偏见,不过。

See an article on medium about it.请参阅有关它的媒体文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM