我有以下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();
这可能吗?
答案 0 :(得分:1)
另一方面,ObserveOn会影响Observable将在该运算符出现的位置使用的线程。因此,您可以在Observable运算符链中的不同点多次调用ObserveOn,以便更改某些运算符在哪些线程上运行。
正如Aaron He所提到的,你可以保留一些你正在使用的调度程序的引用,在后者上使用它&#34; observeOn&#34;。
我有时会使用的另一种做法是删除&#34; observeOn&#34;函数,并确保Activity.runOnUiThread正在UI线程上处理View项目。像 -
这样的东西static Observable<Bitmap> create(@NonNull final Activity activity,@NonNull final SomeObject someObject) {
return Observable.create(new Observable.OnSubscribe<Pair<Activity,SomeObject>>() {
@Override
public void call(final Subscriber<? super Pair<Activity,SomeObject>> subscriber) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
someObject.doStuff();
}
});
}
});
}