architecture-components-samples icon indicating copy to clipboard operation
architecture-components-samples copied to clipboard

NetworkBoundResource: Why load live data object of db another time?

Open philipp-mohr opened this issue 8 years ago • 3 comments

Why is loadFromDb() called another time after network data is fetched successfully? Why can't we use dbSource live data object again?

The way I understand live data object of a database is that if we extract it once, all changes in db will be notified to the observer. If this is correct dbSource can replace loadFromDb(), right?

NetworkBoundResource.class:

private void fetchFromNetwork(final LiveData<ResultType> dbSource) {
        LiveData<ApiResponse<RequestType>> apiResponse = createCall();
        // we re-attach dbSource as a new source, it will dispatch its latest value quickly
        result.addSource(dbSource, newData -> result.setValue(Resource.loading(newData)));
        result.addSource(apiResponse, response -> {
            result.removeSource(apiResponse);
            result.removeSource(dbSource);
            //noinspection ConstantConditions
            if (response.isSuccessful()) {
                appExecutors.diskIO().execute(() -> {
                    saveCallResult(processResponse(response));
                    appExecutors.mainThread().execute(() ->
                            // we specially request a new live data,
                            // otherwise we will get immediately last cached value,
                            // which may not be updated with latest results received from network.
                            result.addSource(loadFromDb(),
                                    newData -> result.setValue(Resource.success(newData)))
                    );
                });
            } else {
                onFetchFailed();
                result.addSource(dbSource,
                        newData -> result.setValue(Resource.error(response.errorMessage, newData)));
            }
        });
    }

philipp-mohr avatar Oct 09 '17 12:10 philipp-mohr

Okay, I have a suspicion: result.removeSource(dbSource) disconnects the dbSource from result live data. Then the change in db happens due to insertion of new network data. When we reconnect to dbSource nothing will be emitted because result live data was disconnected when the change happened.

This issue is resolved by extracting a new db live data object using loadFromDb(). Right?

When the network call fails don't we need to call loadFromDb() as well, to communicate the Resource.error immediately? If we use dbSource there I would expect that the Resource.error is not emmitted immediatly, since the dbSource data does not change.

philipp-mohr avatar Oct 09 '17 13:10 philipp-mohr

@JoseAlcerreca Would you like to add something?

gaurav414u avatar Mar 12 '18 12:03 gaurav414u

@piveloper If dbSource has already emitted a value, result.addSource(dbSource) will emit cache value. result.addSource(loadFromDb()) will emit newly Value.

ipcjs avatar Jun 21 '18 06:06 ipcjs