Florian
02/01/2021, 9:13 AMchannelFlow
? It seems to work as intended, I just want to make sure I'm not doing anything dumb. The point here is to have Loading inside the launch block emit updates while the try
block is running concurrently. I think I don't need to call awaitClose
because collection from the query never ends.
inline fun <ResultType, RequestType> networkBoundResource(
crossinline query: () -> Flow<ResultType>,
crossinline fetch: suspend () -> RequestType,
crossinline saveFetchResult: suspend (RequestType) -> Unit,
crossinline onFetchSuccess: () -> Unit = { },
crossinline onFetchFailed: (Throwable) -> Unit = { },
crossinline shouldFetch: (ResultType) -> Boolean = { true }
) = channelFlow {
val data = query().first()
if (shouldFetch(data)) {
val loading = launch {
query().collect { send(Resource.Loading(it)) }
}
try {
saveFetchResult(fetch())
onFetchSuccess()
loading.cancel()
query().collect { send(Resource.Success(it)) }
} catch (t: Throwable) {
onFetchFailed(t)
loading.cancel()
query().collect { send(Resource.Error(t, it)) }
}
} else {
query().collect { send(Resource.Success(it)) }
}
}
KamilH
02/01/2021, 9:34 AMFlow<T>
emitted by the database as a single source of truth?
Let’s say you have “UseCase/Interactor” layer in your app, then when you want to get data you have two of them:
• ObserveData
- delegates a call to the database that returns Flow<Data>
• RefreshData
- contains a reference to NetworkSource
and DatabaseSource
as well as a logic whether some data should be refreshed (according to shouldFetch
function). This class can emit whether fetch was needed, there was a fetch error, or success and also if loading is happening right now. Or simply be suspending Resource<Unit>
In this case responsibilities between the components in the app seems a bit more clearFlorian
02/01/2021, 10:11 AMFlorian
02/01/2021, 10:11 AMFlorian
02/01/2021, 10:12 AM