what’s is proper way to send file upload progress ...
# compose
j
what’s is proper way to send file upload progress from repository to the compose. I’ve tried sharedFlow, stateFlow nothing seems to be working. One file upload at a time.
f
What do you mean by "sharedFlow, stateFlow nothing seems to be working"? If you have some sort of callback where you receive the progress change, you can use
callbackFlow { ... }
j
I’m calculating progress in custom request body of retrofit, from there I’m using i’m porting that progress through lambda to the repository, which then puts that progress in a hashMap of particular upload as well as put that map onto the sharedFlow
then I’m collecting that repository upload flow in UI using flow#collectAsState but not all the values from repo are getting received at the UI, only few items are coming rest updates are getting lost in between somehow.
t
What are you using for the upload process? Using
WorkManager
allow you to query its progress as a
LiveData
which you could then use to collect as state and visualize it on compose
j
no, I’m posting file directly to the serverUrl using retrofit
f
i’m porting that progress through lambda to the repository
So a callback? If you have some data structure that holds progress for several files that can update independently, then
StateFlow
might be the best option. If you could make the upload function like
fun uploadFile(path: String): Flow<Progress>
, then I would use
callbackFlow { ... }
I've never worked with Retrofit extensively so I don't know how this works but if the question is just "_what’s is proper way to send file upload progress from repository to the compose_", then the answer for me is
flow { ... }
or
callbackFlow { ... }
.
j
I tried using callbackFlow, it was causing some other issues(abruptly closing channel) then I used lambda directly.
alright man, thanks
f
Sorry, I don't know how to help you more than this 😅 Good luck
🤗 1
t
Copy code
fun ResponseBody?.writeToFileWithProgress(file: File?): Flow<Int> {
    if (this == null || file == null) {
        this?.close()
        return emptyFlow()
    }
    val body = this
    return flow {
        body.use {
            body.byteStream().use { inStream ->
                val outStream = file.outputStream()
                outStream.use {
                    var read: Int
                    val buffer = ByteArray(Constants.BUFFER_SIZE)
                    while (inStream.read(buffer).also { read = it } != -1) {
                        emit(read)
                        outStream.write(buffer, 0, read)
                    }
                }
            }
        }
    }
}
I’m using this for download but for upload it’s pretty much the same. It’s woking well in my production app
j
oh okay, let me check. Thanks dude