subscribeOn不适用于整个Rx链,导致NetworkOnMainThreadException

时间:2017-10-17 14:03:54

标签: android rx-java rx-android rx-java2

我在我的CommonLocationManager课程中订阅了这个主题,该课程为其订阅者提供了android.location.Location个更新。

public class CommonLocationManager {

    private final Subject<CommonLocationEvent> mCommonLocationEventSubject = PublishSubject.<CommonLocationEvent>create().toSerialized();

    public Observable<CommonLocationEvent> registerSubscription(@NonNull String identifier, LocationRequestType locationRequestType) {
        boolean alreadySubscribed = mSubscribers.containsKey(identifier);

        if (alreadySubscribed) {
            Log.e(TAG + ": " + identifier + " is already subscribed (or not unique)");
        } else {
            Log.v(TAG + ": " + identifier + " subscribed");
            queueLocationRequest(locationRequestType);
            mSubscribers.put(identifier, locationRequestType);
        }

        return mCommonLocationEventSubject;
    }
}

主题从我们使用的android.location.LocationListener接收其onNext值。

private android.location.LocationListener mLocationListener = new android.location.LocationListener() {
    @SuppressWarnings("ResourceType")
    @Override
    public void onLocationChanged(Location location) {
        mCommonLocationEventSubject.onNext(new CommonLocationEvent(location));
    }

    @Override
    public void onProviderDisabled(String provider) {
        //no op
    }

    @Override
    public void onProviderEnabled(String provider) {
        //no op
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        //no op
    }
};

这是在此代码块中订阅的,它接收CommonLocationEvent s(来自主题),从中获取android.location.Location对象,然后根据该位置加载FooflatMap阻止CurrentLocationFooProvider.getFooForCurrentLocation(coordinate)进行API调用。

MyApplication.getInstance()
    .commonLocationManager()
    .registerSubscription(TAG, getRequestType())
    .filter(new Predicate<CommonLocationEvent>() {
        @Override
        public boolean test(@io.reactivex.annotations.NonNull CommonLocationEvent commonLocationEvent) throws Exception {
            final boolean isLocationEvent = commonLocationEvent.getEventType() == CommonLocationEvent.EventType.LOCATION_UPDATE &&
        commonLocationEvent.getLocation() != null;

            final boolean enoughTimeHasElapsed = Math.abs(mLastUpdateTime - System.currentTimeMillis()) > getRefreshInterval();

            final boolean shouldQueueNewRequest = isLocationEvent && enoughTimeHasElapsed;
            Log.v(TAG + " ShouldQueueNewRequest is " + String.valueOf(shouldQueueNewRequest));
            return shouldQueueNewRequest;
        }
    })
    .map(new Function<CommonLocationEvent, Coordinate>() {
        @Override
        public Coordinate apply(@io.reactivex.annotations.NonNull CommonLocationEvent commonLocationEvent) throws Exception {
            return Coordinate.fromNullableLocation(commonLocationEvent.getLocation());
        }
    })
    .filter(new Predicate<Coordinate>() {
        @Override
        public boolean test(@io.reactivex.annotations.NonNull Coordinate coordinate) throws Exception {
            return !Coordinate.isEffectivelyNull(coordinate);
        }
    })
    .flatMap(new Function<Coordinate, Observable<Foo>>() {
        @Override
        public Observable<Foo> apply(@io.reactivex.annotations.NonNull Coordinate coordinate) throws Exception {
            return new CurrentLocationFooProvider().getFooForCurrentLocation(coordinate)
        .onErrorReturn(new Function<Throwable, Foo>() {
            @Override
            public Foo apply(@io.reactivex.annotations.NonNull Throwable throwable) throws Exception {
                return Foo.NULL;
            }
        });
        }
    })
    .filter(new Predicate<Foo>() {
        @Override
        public boolean test(@io.reactivex.annotations.NonNull Foo foo) throws Exception {
            return !Foo.NULL.equals(foo);
        }
    })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribeOn(Schedulers.io())
    .subscribe(new Observer<Foo>() {
        @Override
        public void onSubscribe(Disposable d) {
            mDisposable = d;
        }

        @Override
        public void onNext(Foo foo) {
            Log.v(TAG + " onNext");

            if (foo != null) {
                mLastUpdateTime = System.currentTimeMillis();
                if (!StringUtils.isEmpty(foo.getName())) {
        Log.v(TAG + " New foo is " + foo.getName());
                }

                onNewFoo(foo);
            }
        }

        @Override
        public void onError(Throwable e) {
            Log.e(TAG, e);
            unsubscribe();
            setupSubscription();
        }

        @Override
        public void onComplete() {
            Log.e(TAG + " onComplete");
        }
    });

我从Rx流收到NetworkOnMainThreadException,即使链中有subscribeOn(Schedulers.io())。请注意,CurrentLocationFooProvider不添加自己的subscribeOnobserveOn如果我更改平面地图以包含其自己的subscribeOn(Schedulers.io()),则api调用将成功,如下所示:

.flatMap(new Function<Coordinate, Observable<Foo>>() {
        @Override
        public Observable<Foo> apply(@io.reactivex.annotations.NonNull Coordinate coordinate) throws Exception {
            return new CurrentLocationFooProvider().getFooForCurrentLocation(coordinate)
        .onErrorReturn(new Function<Throwable, Foo>() {
            @Override
            public Foo apply(@io.reactivex.annotations.NonNull Throwable throwable) throws Exception {
                return Foo.NULL;
            }
        })
        .subscribeOn(Schedulers.io());
        }
    })

我的一部分是可以的,因为它有效,但我不明白为什么这个subscribeOn是必要的,因为我订阅主题并在代码库中其他地方的平面地图中进行API调用,而没有这个问题。我做错了什么?

0 个答案:

没有答案