inline fun <ResultType, RequestType> networkBoundResource(
crossinline query: () -> Flow<ResultType>,
crossinline fetch: suspend () -> RequestType,
crossinline saveFetchResult: suspend (RequestType) -> Unit,
crossinline onFetchFailed: (Throwable) -> Unit = { Unit },
crossinline shouldFetch: (ResultType) -> Boolean = { true }
) = flow<Resource<ResultType>> {
emit(Resource.Loading(null))
val data = query().first()
val flow = if (shouldFetch(data)) {
emit(Resource.Loading(data))
try {
saveFetchResult(fetch())
query().map { Resource.Success(it) }
} catch (throwable: Throwable) {
onFetchFailed(throwable)
query().map { Resource.Error(throwable, it) }
}
} else {
query().map { Resource.Success(it) }
}
emitAll(flow)
}