0%

关于 RxJava2 的一些问题

在使用 RxJava2 过程中,会遇到一些问题和对应的解决方案,在这里稍微记录下。

发射 Null 问题

在 RxJava1 中,可以直接发射 null 数据,就像这样:

1
Observable.create(null);

但在 RxJava2 中,这种做法是会抛出异常的。可以通过一个新的封装了原始数据的类,来解决此问题。
比如定义一个 DataWrapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public final class DataWrapper<T> {
private final T data;

private DataWrapper(@Nullable T data) {
this.data = data;
}

public static <T> DataWrapper<T> ofNullable(T data) {
return new DataWrapper<>(data);
}

public boolean isEmpty() {
return this.data == null;
}

public T get() {
return data;
}

@Override
public String toString() {
return data != null
? String.format("DataWrapper[%s]", data)
: "null";
}
}

比如有一个方法去加载某些数据:

1
2
3
4
@Nullable 
String loadData() {
return null;
}

那我们在对可能为 null 的数据流处理就可以变成:

1
2
3
4
5
6
7
8
9
10
Observable.fromCallable(() -> DataWrapper.ofNullable(loadData()))
.subscribe(item -> {
if (item.isEmpty()) {
// do something
} else {
// do something else
}
}, throwable -> {
// handle error
});

当然了,我们也可以通过 Observable.create() 来规避对 null 数据的发射:

1
2
3
4
5
6
7
8
9
10
11
12
13
Observable
.create((ObservableOnSubscribe<String>) emitter -> {
String data = loadData();
if (data != null) {
emitter.onNext(data);
}
emitter.onComplete();
})
.subscribe(item -> {
// do something
}, throwable -> {
// handle error
});

相关链接

异常堆栈信息显示不全问题

在使用 RxJava2 过程中,如果抛出了异常,会遇到异常信息不全问题,没有给出具体行数,就像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
java.lang.NullPointerException: Callable returned null
at io.reactivex.internal.functions.ObjectHelper.requireNonNull(ObjectHelper.java:39)
at io.reactivex.internal.operators.observable.ObservableFromCallable.subscribeActual(ObservableFromCallable.java:43)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableFilter.subscribeActual(ObservableFilter.java:30)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableSwitchIfEmpty.subscribeActual(ObservableSwitchIfEmpty.java:31)
at io.reactivex.Observable.subscribe(Observable.java:12267)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:578)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)

上面的 Error 堆栈信息中,它并没有给出这个 Error 在实际项目中的调用路径。

为了解决这个问题,可以引入 RxJavaExtensions 库。

  1. 先启用错误追踪:

    1
    RxJavaAssemblyTracking.enable();
  2. 获取对应错误信息:

    1
    2
    3
    4
    RxJavaAssemblyException assembled = RxJavaAssemblyException.find(someThrowable);
    if (assembled != null) {
    System.err.println(assembled.stacktrace());
    }

    打印出来的错误信息就像这样,已经可以准确定位错误位置了:

    1
    2
    3
    4
    5
    6
    7
    8
    RxJavaAssemblyException: assembled
    at dalvik.system.VMStack.getThreadStackTrace(Native Method)
    at io.reactivex.Observable.fromCallable(Observable.java:1808)
    at com.tianma.simpleweather.data.db.DBManager.loadWeatherByPK(DBManager.java:183)
    at com.tianma.simpleweather.data.repository.DataRepository.getWeather(DataRepository.java:40)
    at com.tianma.simpleweather.feature.weather.WeatherPresenter.loadWeather(WeatherPresenter.java:42)
    at com.tianma.simpleweather.feature.weather.WeatherFragment.doRefresh(WeatherFragment.java:262)
    at com.tianma.simpleweather.feature.weather.WeatherFragment.lazyLoad(WeatherFragment.java:240)

相关链接