Can anyone sanity check this `channelFlow`? It see...
# coroutines
f
Can anyone sanity check this
channelFlow
? 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.
Copy code
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)) }
    }
}
k
I’ve got a question, maybe a little bit off topic, but if you are persisting your network data in the database, wouldn’t it be easier to build your app around
Flow<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 clear
f
But the database is the single source of truth here, what makes you think otherwise?
Everything we send through the Flow comes from the DB
We just wrap it into Resource so it contains the data and loading state