I have a flow, and I’d like to keep track of ‘prog...
# coroutines
t
I have a flow, and I’d like to keep track of ‘progress’ (I know the flow will complete). I’m wondering if there’s a better model than this:
Copy code
fun findSongs(): Flow<Pair<Song, Int>>
Where the flow emits a song, and a count of the total number of songs.. It seems a little redundant to have to emit the same ‘total’ each time. But the alternative is to have a separate function for retrieving the count, and thats’ not particularly efficient..
The simple answer might be the best one..
Copy code
fun findSongs(progress: (Int, Int) -> (Unit)): Flow<Song>
c
or, you can use an incrementer
onEach
song that you get and map in the other step.
t
Could you elaborate?
c
Well I'm not sure if exactly fits your case but you can do something like this:
Copy code
getSongs().onEach{ -> Pair(a,c++)}.collect/map
t
Oh I see what you’re saying. Let the caller manage progress
c
No sorry, you don't need a pair. just increment the counter on each song.
t
The problem is, there’s no way to know what the total is until the flow completes
c
so count every song that comes and on complete print the value
t
Sure, but this doesn’t allow you to determine the ‘progress’ as a percentage of the total. Only that progress has occurred.
I’ve gone with this for now..
Copy code
suspend fun findSongs(callback: ((song: Song, progress: Int, total: Int) -> (Unit))? = null): List<Song>
It’s a little ugly, but it does the job
I think my mistake was using a flow to model something finite
t
Pair is probably your best compared to what I'm about to suggest, But I'm becoming more and more of a fan of the whole sealed class hierarchy. You can also return the Error class if there were some errors..
a
This is zeroing in on producing a Flow of events, which you project to a state: CountedSongs(Int) FoundSong(Song)
I think using Flow for a finite sequence totally makes sense, not sure why you feel down on it
t
It is OK to use a flow to represent a finite sequence, I guess I’m just saying in this case, I know I’m returning a List of songs, I can make it a suspend fun and simplify things a little.
I did consider using a sealed class to represent a progress, and a result - but I think again it overcomplicates things
t
Sounds like your use case makes sense for a list. But then, you don't need a progress bar anymore? 🙂
I modeled a simple rest client API with a flow. A few returned small data objects. Other calls returned huge lists that were paginated(multiple rest calls). The flow let me have the same api and let me process that list lazily keeping only the small page I was working on in ram.
t
The end result is a list. I still need to know the progress as the list is populated
Thanks everyone. There are lots of different approaches and they’re all valid in various contexts.