How do you handle progress bars when you're loadin...
# android
f
How do you handle progress bars when you're loading something from a Flow? Where do you set the progress bar to visible/gone? For example:
Copy code
private val activeChatsFlow = sessionManager.chatUserFlow.flatMapLatest { user ->
        repository.getActiveChatsForUser(user.uid!!)
   }
Are
onStart
and
onCompletion
the right combination?
t
One solution is to make it part of the UI state exposed via `LiveData`/`Stateflow`. 2 approaches: 1. Use a sealed class with a
Loading
child having a
progress
property, for example 2. Add a
loading: Boolean
to your existing state. You could then use
onStart
to update state with your
loading
flag, and clear it when active chats are available.
☝️ 1
f
Thanks. Where do you set
loading = false
specifically?
f
Before you call the function that sets the flow alive In this case before the repository.getActiveUserForChat and one after it's called You can use onStart and onCompletion and it's gonna work too, which is the correct way to do so
t
Given
fun getActiveChatsForUser(user: User): List<Chat>
and the given UI state class:
Copy code
data class UiState(
  val loading: Boolean,
  val chats: List<Chat>
)
Then you would need to do the following:
Copy code
chatUserFlow.flatMapLatest { user ->
  repository.getActiveChatsForCurrentUser(user.uid)
    .map { UiState(loading = false, chats = it) }
    .onStart { emit(UiState(loading = true, chats = emptyList()) }
}
Progress indicator will be shown until chats are loaded for the first time, and will be shown again whenever chatUserFlow emits.
f
UI states should be sealed classes holding only one state at the moment
f
that's interesting, thank you
instead of
map
I could also use
onEach
to just set loading = false, right?
but
onCompletion
doesn't seem to work, it works the first time but not when I close and open the app again
c
@Florian I've gone the rabbit hole of "UI states should be sealed classes" and it gets out of hand quickly and not really doable in things that aren't crazy simple. I think @Adam Powell talked me out of it? I just have state as a class and I can mix and match everything. Events on the other hand... those are sealed classes in my apps.
n
I have done both, modeling UI states as either a sealed class or a single data class. I generally prefer MVI with actions modeled as a sealed class and state as a data class. In cases like this, MVVM with a data class representing the UI state is a good compromise to avoid the overhead of a full MVI redux implementation
f
I think the discussion is derailing a bit
the original questions was where to set loading = true/false
m
I follow a similar pattern to your example. I update my ui state loading in
onStart
and
onCompletion
in the flow returned to
flatMapLatest
. (That is, the “inner” flow.)
f
are you sure
onCompletion
is the right place to hide the progress bar? It is called when the Flow is closed
m
That’s a fair point. I guess in my specific use case the inner flow does complete. I suppose if yours does not you’d have to move it into
onEach
.
f
thank you
129 Views