https://kotlinlang.org logo
#coroutines
Title
# coroutines
t

Tim Malseed

09/30/2020, 5:08 AM
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

coroutinedispatcher

09/30/2020, 6:31 AM
or, you can use an incrementer
onEach
song that you get and map in the other step.
t

Tim Malseed

09/30/2020, 6:49 AM
Could you elaborate?
c

coroutinedispatcher

09/30/2020, 6:55 AM
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

Tim Malseed

09/30/2020, 6:56 AM
Oh I see what you’re saying. Let the caller manage progress
c

coroutinedispatcher

09/30/2020, 6:56 AM
No sorry, you don't need a pair. just increment the counter on each song.
t

Tim Malseed

09/30/2020, 6:56 AM
The problem is, there’s no way to know what the total is until the flow completes
c

coroutinedispatcher

09/30/2020, 6:57 AM
so count every song that comes and on complete print the value
t

Tim Malseed

09/30/2020, 6:57 AM
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

taer

09/30/2020, 1:41 PM
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

araqnid

09/30/2020, 5:37 PM
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

Tim Malseed

10/01/2020, 12:00 AM
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

taer

10/01/2020, 1:29 PM
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

Tim Malseed

10/01/2020, 11:12 PM
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.
4 Views