Skip to content

Modify Kotlin Coroutine Flow value after initialization #1856

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
adam-hurwitz opened this issue Mar 10, 2020 · 1 comment
Closed

Modify Kotlin Coroutine Flow value after initialization #1856

adam-hurwitz opened this issue Mar 10, 2020 · 1 comment

Comments

@adam-hurwitz
Copy link

adam-hurwitz commented Mar 10, 2020

This is a potential feature request as it is uncertain whether this functionality currently exists with Flow.

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)
    }
}
@adam-hurwitz
Copy link
Author

adam-hurwitz commented Mar 10, 2020

This question has been answered by How to emit data to kotlin flow #1448 and [DRAFT] DataFlow implementation #1354.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant