https://kotlinlang.org logo
#android
Title
# android
a

AmrJyniat

06/30/2022, 1:18 PM
How to recollect
SharedFlow
when the first collect got exception? like I expose a
Flow
from repo to VM then convert it to
SharedFlow
by
shareIn()
then collect this SharedFlow from the fragment, now I got an exception while collecting the SharedFlow, so how to retry/recollect it again?
g

gildor

07/05/2022, 4:14 AM
You should include this recollection logic before converting it to SharedFlow You can use
retry
for this: https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/retry.html
But still, I would recommend to handle it on level of original Flow, because it knows better semantics of those errors and have more ways to handle it, so your flow wouldn’t propagate errors, instead ignore errors and retry or emit error state and retry after that So if you control code of original Flow, just handle it there, if not, you can use
retry
But don’t forget, you should use retry before creating StateFlow
a

AmrJyniat

07/05/2022, 7:07 AM
I could use retry on the original Flow like:
Copy code
flow.retryWhen { cause, attempt -> 
    attempt < 3
}
But I have a button for retrying the API call when failed and, I couldn't handle the retry mechanism when the click event occurred.
g

gildor

07/05/2022, 7:10 AM
BTW, flow.retry(3) will do the same
But user retry is different thing, and probably should be resolved on level of reactive stream, so when you have source (or multiple sources) of event to start loading, it mapped to your request
It hard to recommend particular solution without context
But this doesn’t look as work for retry() at all, but rather matter how you design your data flows
a

AmrJyniat

07/05/2022, 7:20 AM
I receive the Flow from repo to VM like:
Copy code
val flow: Flow<Result<T>> = repo.getData()
And collect the flow in the fragment, now the retry button appears when the
result
failed, I searched for an elegant/clean way to recollect the flow on the click event, therefore, the API called again but I didn't found. I ended up with something like that:
Copy code
private val _sponsors = Channel<Unit>()
val sponsors = _sponsors.receiveAsFlow().flatMapLatest {
        repository.loadSponsors()
  }.myShareIn(viewModelScope, replay = 1)

fun loadSponsors() = viewModelScope.launch {
   _sponsors.send(Unit)
}

init { loadSponsors() }
In this case, just call `loadSponsors()`fun when the retry button clicked, what do you think?
g

gildor

07/05/2022, 9:33 AM
so what is your problem with this code?
I’m not exactly sure that I see any problem So you should show error case and allow to reload
Just do not cache failed “repository.loadSponsors”
return some error state instead
like:
Copy code
val sponsors = _sponsors.receiveAsFlow().flatMapLatest {
        return runCatching {
            repository.loadSponsors())
         } 
  }.myShareIn(viewModelScope, replay = 1)
I use Kotlin Result here, but you can use any own state to propagate error
a

AmrJyniat

07/05/2022, 9:40 AM
I see, thank you man, I just tried to apply the cleanest way.
g

gildor

07/05/2022, 9:47 AM
Otherwise how you can handle error case?
a

AmrJyniat

07/05/2022, 10:10 AM
The
sponsors
val is a flow containing custom Result class
Result<T>
, so when collecting it in the fragment I'm just checking if the result failed or not, therefore, I don't need any processing in the VM like
runCathing{}
because the catch applied already in the repo layer.
g

gildor

07/05/2022, 12:51 PM
So if you already have this Result class, you do not throw exception and no need to restart, right?
a

AmrJyniat

07/05/2022, 12:58 PM
Ok but if the result failed when collecting the flow, how to recall the API? I need to recollect the flow again, that's it.
g

gildor

07/05/2022, 1:51 PM
What kind result?
If loadSponsors will return error?
But in this case you just restart chain by emitting to _sponsors
a

AmrJyniat

07/05/2022, 2:03 PM
Yes in the final solution I retrigger the API call by emitting to _sponsors. But I was hoping to find something built-in like retry() in the Flow Apis to make my code more elegant.
g

gildor

07/05/2022, 3:09 PM
retry exists, it just will not help in this case
25 Views