Skip to content

Instantly share code, notes, and snippets.

@adam-hurwitz
Last active September 22, 2022 22:14
Show Gist options
  • Save adam-hurwitz/b6cbc8da62ed8cffdee94074b81b1684 to your computer and use it in GitHub Desktop.
Save adam-hurwitz/b6cbc8da62ed8cffdee94074b81b1684 to your computer and use it in GitHub Desktop.
Android Model-View-Intent with Kotlin Flow - FeedViewModel.kt
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@ExperimentalCoroutinesApi
class FeedViewModel @AssistedInject constructor(
@Assisted private val coroutineScopeProvider: CoroutineScope?,
private val repository: FeedRepository,
) : ViewModel() {
@AssistedInject.Factory
interface Factory {
fun create(coroutineScopeProvider: CoroutineScope? = null): FeedViewModel
}
private val coroutineScope = getViewModelScope(coroutineScopeProvider)
private val state = MutableStateFlow<FeedViewState?>(null)
fun bindIntents(view: FeedView) {
view.initState().onEach {
state.filterNotNull().collect { view.render(it) }
}.launchIn(coroutineScope)
view.loadFromNetwork().onEach {
loadFromNetwork(FeedLoad(...))
}.launchIn(coroutineScope)
view.selectContent().onEachEvent { selectContent ->
selectContent(selectContent)
}.launchIn(coroutineScope)
}
private fun loadFromNetwork(event: FeedLoad) {
repository.getMainFeedNetwork(...).onEach { resource ->
when (resource.status) {
LOADING -> repository.getMainFeedRoom(...).onEach { pagedList ->
// Pass local data.
state.value = FeedViewState.Feed(...)
}.launchIn(coroutineScope)
SUCCESS -> resource.data?.collect { pagedList ->
// Pass network data.
state.value = FeedViewState.Feed(...)
}
ERROR -> repository.getMainFeedRoom(...).onEach { pagedList ->
// Pass local data.
state.value = FeedViewState.Feed(...)
}.launchIn(coroutineScope)
}
}.launchIn(coroutineScope)
}
private fun selectContent(selectContent: SelectContent) {
repository.getAudiocast(selectContent).onEach { resource ->
when (resource.status) {
LOADING -> state.value = FeedViewState.OpenContent(...)
SUCCESS -> state.value = FeedViewState.OpenContent(...)
ERROR -> state.value = FeedViewState.OpenContent(...)
}
}.launchIn(coroutineScope)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment