Expected
Initialize a Kotlin Coroutine Flow and modify its' value after the Flow's creation.
The desired functionality is similar to MutableLiveData's setValue which allows data to be added to an existing MutableLiveData object.
In the example below setValue is called on the _feed MutableLiveData value in FeedViewModel.kt in order to update the value.
This works as expected, emitting the values in FeedFragment.kt
FeedViewState.kt
data class _FeedViewState(
val _feed: MutableLiveData<List<Tweet>> = MutableLiveData()
)
data class FeedViewState(private val _feedViewState: _FeedViewState) {
val feed: LiveData<List<Tweet>> = _feedViewState._feed
}
FeedViewModel.kt
class FeedViewModel(...) : ViewModel() {
private val _feedViewState = _FeedViewState()
val feedViewState = FeedViewState(_feedViewState)
init {
viewModelScope.launch(Dispatchers.IO) {
feedRepository.getFeed().collect { results ->
when (results.status) {
LOADING -> ...
SUCCESS -> withContext(Dispatchers.Main) {
_feedViewState._feed.value = results.data
}
ERROR -> ...
}
}
}
}
}
FeedFragment.kt
class FeedFragment : Fragment() {
override fun onCreateView(...): View? {
viewModel.feedViewState.feed.observe(viewLifecycleOwner){ feed ->
//Do something with the tweets here.
}
return inflater.inflate(R.layout.fragment_feed, container, false)
}
}
Observed
In order to implement the same pattern using Kotlin Coroutines the LiveData in the FeedViewState.kt is replaced with Flow. In FeedViewModel.kt the desired result is to add data to the _feed Flow value. The attempted solutions have been applying map, and emit inside of transform and onCompletion to the _feed Flow value.
However, this solution does not emit the desired values from the Flow value in FeedFragment.kt.
FeedViewState.kt
data class _FeedViewState(
val _feed: Flow<List<Tweet>> = flow { }
)
data class FeedViewState(private val _feedViewState: _FeedViewState) {
@ExperimentalCoroutinesApi
val feed: Flow<List<Tweet>> = _feedViewState._feed }
}
FeedViewModel.kt
class FeedViewModel(...) : ViewModel() {
private val _feedViewState = _FeedViewState()
val feedViewState = FeedViewState(_feedViewState)
init {
viewModelScope.launch(Dispatchers.IO) {
feedRepository.getFeed().collect { results ->
when (results.status) {
LOADING -> ...
SUCCESS -> withContext(Dispatchers.Main) {
_feedViewState._feed.map { results.data!! }
}
ERROR -> ...
}
}
}
}
}
FeedFragment.kt
class FeedFragment : Fragment() {
override fun onCreateView(...): View? {
lifecycleScope.launch {
viewModel.feedViewState.feed.collect { tweets ->
//Do something with the tweets here.
}
}
return inflater.inflate(R.layout.fragment_feed, container, false)
}
}