galex
08/07/2023, 11:00 AMval viewModel: SomeViewModel = hiltViewModel()
val someUiState by viewModel.uiState.collectAsStateWithLifecycle()
And having an uiState defined as the following (in a ViewModel)
private val _uiState by lazy { MutableStateFlow(initializeUiState()) }
override val uiState get() = _uiState.asStateFlow().apply {
onStart { Timber.d("onStart uiState on = $this")}
onCompletion { Timber.d("onCompletion uiState on = $this")}
}
onStart
and onCompletion
are not called, what am I missing here?Stylianos Gakis
08/07/2023, 11:23 AMgalex
08/07/2023, 11:24 AMgalex
08/07/2023, 11:24 AMStylianos Gakis
08/07/2023, 11:24 AMgalex
08/07/2023, 11:24 AMStylianos Gakis
08/07/2023, 11:24 AMstateIn()
heregalex
08/07/2023, 11:25 AMStylianos Gakis
08/07/2023, 11:26 AMgalex
08/07/2023, 11:27 AMgalex
08/07/2023, 11:28 AMStylianos Gakis
08/07/2023, 11:29 AMgalex
08/07/2023, 11:30 AMStylianos Gakis
08/07/2023, 11:31 AMgalex
08/07/2023, 11:32 AMgalex
08/07/2023, 12:09 PMMutableStateFlow(initializeUiState()).apply {
subscriptionCount
.map { count -> count > 0 }
.distinctUntilChanged()
.onEach { isActive ->
Timber.d("ViewModel ${this@MVIViewModel} has active observers on UI State = $isActive")
if (isActive) onUiStateHasObservers() else onUiStateHasNoObservers()
}
.launchIn(viewModelScope)
}
Stylianos Gakis
08/07/2023, 12:16 PMonUiStateHasObservers
and onUiStateHasNoObservers
galex
08/07/2023, 12:17 PMonUiStateHasNoObservers
and create it onUiStateHasObservers
Stylianos Gakis
08/07/2023, 12:18 PMstateIn
you get this for free, it cancels itself on no observers. Just like in the places I linked you to.galex
08/07/2023, 12:19 PMgalex
08/07/2023, 12:20 PMstateIn
, maybe I can come up with something bettterStylianos Gakis
08/07/2023, 12:20 PMStylianos Gakis
08/07/2023, 12:20 PMgalex
08/07/2023, 12:21 PMStylianos Gakis
08/07/2023, 12:21 PMFlow
instead of StateFlow
and make the entire chain cold until you have an observer with stateIn(WhileSubscribed)
Stylianos Gakis
08/07/2023, 12:21 PMStylianos Gakis
08/07/2023, 12:22 PMgalex
08/07/2023, 12:25 PMStylianos Gakis
08/07/2023, 12:26 PMthe hot flow from Room is observed
?
What is a hot from from Room?galex
08/07/2023, 12:29 PMjob = viewModelScope.launch {
client.observeSomething(somethingId, BULK_SIZE)?.collect { something ->
update { state ->
state.copy(
id = something?.id ?: "",
)
}
}
}
galex
08/07/2023, 12:32 PMprivate fun MutableStateFlow<UiState>.notifyIsActive() = apply {
subscriptionCount
.map { count -> count > 0 }
.distinctUntilChanged()
.dropWhile { false }
.onEach { isActive -> if (isActive) onUiStateActive() else onUiStateNotActive() }
.launchIn(viewModelScope)
}
protected open fun onUiStateActive() {}
protected open fun onUiStateNotActive() {}
Stylianos Gakis
08/07/2023, 12:35 PMval uiState: StateFlow<UiState> = flow {
client... do stuff in here to create your UiState
}.stateIn(
viewModelScope,
WhileSubscribed(5.seconds),
initialUiState,
)
galex
08/07/2023, 12:38 PMflow {}
, giving the cancellation mechanism directly to the flows coming from that client. Nice, trying that instead 👍Colton Idle
08/07/2023, 12:40 PMval viewModel: SomeViewModel = hiltViewModel()
need to be wrapped in a remember?Stylianos Gakis
08/07/2023, 1:18 PMremember
it without the right keys, in case LocalViewModelStoreOwner
changes you will still be getting the old reference right?Stylianos Gakis
08/07/2023, 3:30 PMgalex
08/07/2023, 4:11 PMstateIn
instead of a backed MutableStateFlow
is that I can't update as before from multiple places.
Does that mean I should indeed have different flows in my ViewModel maybe? 🤔Stylianos Gakis
08/07/2023, 4:17 PMgalex
08/07/2023, 4:19 PMStylianos Gakis
08/07/2023, 4:19 PMflow {}
in the merge
there is only there so that it will re-start when the entire StateFlow goes from cold to hot again. Kinda what you’re asking for, scoping some work to happen when there’s a collector.galex
08/07/2023, 4:20 PMStylianos Gakis
08/07/2023, 4:20 PMStylianos Gakis
08/07/2023, 4:21 PMstateIn()
which means that if no collectors exist that chain will simply not be running?galex
08/07/2023, 4:22 PM