nytimes / Store

Android Library for Async Data Loading and Caching

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

NetworkOnMainThread thrown when performing a clear from the MainThread

LarsWerkman opened this issue · comments

When performing a clear from the MainThread while Observing a getRefreshing Observable the NetworkOnMainThread exception is thrown while fetching from an Api.

Here is a broken down example:

favoriteShopsStore = StoreBuilder.<String, BufferedSource, List<Shop>>parsedWithKey()
             .fetcher(ignore -> api.getFavoriteShops())
             .memoryPolicy(MemoryPolicy.builder()
                      .setExpireAfterWrite(1)
                      .setExpireAfterTimeUnit(TimeUnit.HOURS)
                      .setMemorySize(1)
                      .build())
             .refreshOnStale()
             .open();

favoriteShopsStore.getRefreshing("favorite")
             .subscribeOn(io.reactivex.schedulers.Schedulers.io())
             .observeOn(io.reactivex.android.schedulers.AndroidSchedulers.mainThread())
             .subscribe(new Observer<List<Shop>>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(List<Shop> shops) {

                    }

                    @Override
                    public void onError(Throwable e) {
                        //Error on NetworkOnMainThread is thrown 
                    }

                    @Override
                    public void onComplete() {

                    }
             });

favoriteShopsStore.clear("favorite");

This exception isn't thrown when you force the api call to always subscribe on the IO schedulers, however it seems to me that this isn't as intended.

.fetcher(ignore -> api.getFavoriteShops().subscribeOn(Schedulers.io()))

I traced it down to the RealInternalStore::response method

    @Nonnull
    Single<Parsed> response(@Nonnull final Key key) {
        return fetcher()
                .fetch(key)
                .flatMap(raw -> persister()
                        .write(key, raw)
                        .flatMap(aBoolean -> readDisk(key).toSingle()))
                .onErrorResumeNext(throwable -> {
                    if (stalePolicy == StalePolicy.NETWORK_BEFORE_STALE) {
                        return readDisk(key)
                                .switchIfEmpty(Maybe.<Parsed>error(throwable))
                                .toSingle();
                    }
                    return Single.error(throwable);
                })
                .doOnSuccess(data -> notifySubscribers(data, key))
                .doAfterTerminate(() -> inFlightRequests.invalidate(key))
                .cache();
    }

Here it seems the original exception is thrown inside the onErrorResumeNext clause

Hmm. Wouldn't network on Main thread exception also be thrown if you call get from main thread? Overall store performs all operations on whatever thread the api is called. I'll make a getRefreshing override that takes in a scheduler.