我在我的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
对象,然后根据该位置加载Foo
。 flatMap
阻止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不添加自己的subscribeOn
或observeOn
如果我更改平面地图以包含其自己的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调用,而没有这个问题。我做错了什么?