【发布时间】:2016-01-27 16:23:17
【问题描述】:
我有以下 RxJava Observable:
final class MapBitmapObservable {
static Observable<Bitmap> create(@NonNull final MapView mapView) {
return Observable.create(new Observable.OnSubscribe<Bitmap>() {
@Override
public void call(final Subscriber<? super Bitmap> subscriber) {
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull final GoogleMap googleMap) {
googleMap.snapshot(new GoogleMap.SnapshotReadyCallback() {
@Override
public void onSnapshotReady(@Nullable final Bitmap bitmap) {
if (bitmap != null) {
subscriber.onNext(bitmap);
subscriber.onCompleted();
} else {
subscriber.onError(new MapSnapshotFailedException());
}
}
});
}
});
}
});
}
private MapBitmapObservable() {
}
}
必须在主线程上调用MapView方法getMapAsync来避免这个异常:
java.lang.IllegalStateException: getMapAsync() must be called on the main thread
at com.google.android.gms.common.internal.zzx.zzcD(Unknown Source)
at com.google.android.gms.maps.MapView.getMapAsync(Unknown Source)
at com.github.stkent.bugshaker.email.screenshot.maps.MapBitmapObservable$1.call(MapBitmapObservable.java:42)
at com.github.stkent.bugshaker.email.screenshot.maps.MapBitmapObservable$1.call(MapBitmapObservable.java:37)
at rx.Observable.unsafeSubscribe(Observable.java:8098)
...
假设MapBitmapObservable 被用作Observable 链的一部分,其中先前和后续操作可能会长时间运行,并且应该在主线程之外执行。一个简化的示例可能如下所示:
Observable.just(activity)
.flatmap(new Func1<Activity, Observable<MapView>>() {
@Override
public Observable<Bitmap> call(@NonNull final Activity activity) {
return ExpensiveToCreateObservable.create(activity);
}
})
.flatmap(new Func1<MapView, Observable<Bitmap>>() {
@Override
public Observable<Bitmap> call(@NonNull final MapView mapView) {
return MapBitmapObservable.create(mapView);
}
})
.flatmap(new Func1<Bitmap, Observable<Uri>>() {
@Override
public Observable<Uri> call(@NonNull final Bitmap bitmap) {
return SomeOtherExpensiveToCreateObservable.create(bitmap);
}
})
.subscribeOn(Schedulers.io())
.subscribe();
(虽然应该注意,在我的实际应用中,链接分布在几种不同的方法中)。我想:
- 确保在主线程上调用
MapView.getMapAsync; - 允许在原始调度程序上执行第二个长时间运行的操作,无论是什么(
Schedulers.io()、Schedulers.computation()等)李>
在我看来,实现此目的的伪代码如下所示:
Observable.just(activity)
.flatmap(new Func1<Activity, Observable<MapView>>() {
@Override
public Observable<Bitmap> call(@NonNull final Activity activity) {
return ExpensiveToCreateObservable.create(activity);
}
})
.observeOn(AndroidSchedulers.mainThread()) // This is real, and resolves bullet 1.
.flatmap(new Func1<MapView, Observable<Bitmap>>() {
@Override
public Observable<Bitmap> call(@NonNull final MapView mapView) {
return MapBitmapObservable.create(mapView);
}
})
.observeOn(/* Some way of referencing the thread on which I originally subscribed, to resolve bullet 2. */)
.flatmap(new Func1<Bitmap, Observable<Uri>>() {
@Override
public Observable<Uri> call(@NonNull final Bitmap bitmap) {
return SomeOtherExpensiveToCreateObservable.create(bitmap);
}
})
.subscribeOn(Schedulers.io()) // I do not want to rely on knowledge of the Scheduler type used at this call-site.
.subscribe();
这可能吗?
【问题讨论】:
-
保留原
Scheduler的引用,以后再用? -
感谢您的意见!如果链都是内联构造的,这将是可行的,如上面的简化示例中所示;但是,原始问题的以下警告:“(尽管应该注意,在我的实际应用程序中,链接分布在几种不同的方法中)”意味着
subscribeOn的调用远离使用 @ 的flatmap987654336@。这意味着理想情况下,我希望有一个更“本地化”的解决方案,其中两个observeOn包装表示flatmap不需要知道原始的Scheduler类型。 -
(在呼叫站点定义)。
标签: java android rx-java rx-android