Reputation: 11754
I've one LiveData
named sortOrder
and then I've another variable named myData
that observes any change to sortOrder
and populates data accordingly.
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
Flow/StateFlow
APIs without any change in output?Upvotes: 4
Views: 6247
Reputation: 807
From the point of the fragment/activity, you have to create a job that collects the flow in onStart()
and cancel it in onStop()
. Using the lifecycleScope.launchWhenStarted
will keep the flow active even in the background.
Use the bindin library to migrate to Flow
with ease. I'm biased, tho.
See an article on medium about it.
Upvotes: 0
Reputation: 93609
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). 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.
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.
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.
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"))
Upvotes: 4