RxDogTag:自動標記RxJava原始訂閱點

語言: CN / TW / HK

一、背景

在使用RxJava的過程中,經常會碰到如下一個經典的錯誤:

Observable.range(0, 10) .subscribeOn(Schedulers.io()) .map(i -> null) .subscribe(); 在上面的程式碼中,由於我們沒有實現onError()的RxJava觀察者,所以在執行的時候,會報如下的錯誤。

io.reactivex.exceptions.OnErrorNotImplementedException: The exception was not handled due to missing onError handler in the subscribe() method call. Further reading: https://github.com/ReactiveX/RxJava/wiki/Error-Handling | The mapper function returned a null value. at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:704) at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:701) at io.reactivex.internal.observers.LambdaObserver.onError(LambdaObserver.java:77) at io.reactivex.internal.observers.BasicFuseableObserver.onError(BasicFuseableObserver.java:100) at io.reactivex.internal.observers.BasicFuseableObserver.fail(BasicFuseableObserver.java:110) at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:59) at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onNext(ObservableSubscribeOn.java:58) at io.reactivex.internal.operators.observable.ObservableScalarXMap$ScalarDisposable.run(ObservableScalarXMap.java:248) at io.reactivex.internal.operators.observable.ObservableJust.subscribeActual(ObservableJust.java:35) at io.reactivex.Observable.subscribe(Observable.java:12090) 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.access$201(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.NullPointerException: The mapper function returned a null value. at io.reactivex.internal.functions.ObjectHelper.requireNonNull(ObjectHelper.java:39) at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:57) ... 14 more 對於上面的資訊,並不是很方便我們定位問題,對於這個問題,我們可以啟用RxDogTag來為onError()調查自動標記RxJava 2+原始訂閱點。

根據官方的介紹,RxDogTag是一個在rxjava2+觀察者中標記原始訂閱點的實用程式,其目標是在發生未處理的錯誤時顯示它們的訂閱位置,以便以後進行錯誤報告/調查。這隻適用於不實現onError()的RxJava觀察者。

二、使用和配置

2.1 基本使用

首先,我們需要在專案中新增RxDogTag的依賴,依賴的時候需要區分是RxJava2還是RxJava3,因為他們的依賴方式是不一樣的。

//RxJava2 implementation("com.uber.rxdogtag:rxdogtag:x.y.z") //RxJava3 implementation("com.uber.rxdogtag2:rxdogtag:x.y.z") 接下來,在應用程式生命週期的早期通過RxDogTag.install()安裝,這將在RxJavaPlugins中安裝必要的鉤子。

RxDogTag.builder() .configureWith(AutoDisposeConfigurer::configure) .install(); 啟用RxDogTag時,錯誤發生了明顯的改變,如下。

``` io.reactivex.exceptions.OnErrorNotImplementedException: The mapper function returned a null value.

Caused by: java.lang.NullPointerException: The mapper function returned a null value. at anotherpackage.ReadMeExample.complex(ReadMeExample.java:55) at [[ ↑↑ Inferred subscribe point ↑↑ ]].(:0) at [[ ↓↓ Original trace ↓↓ ]].(:0) at io.reactivex.internal.functions.ObjectHelper.requireNonNull(ObjectHelper.java:39) at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:57) at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onNext(ObservableSubscribeOn.java:58) at io.reactivex.internal.operators.observable.ObservableScalarXMap$ScalarDisposable.run(ObservableScalarXMap.java:248) at io.reactivex.internal.operators.observable.ObservableJust.subscribeActual(ObservableJust.java:35) at io.reactivex.Observable.subscribe(Observable.java:12090) 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.access$201(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) ``` 啟用RxDogTag後,示例訂閱行提示報錯為ReadMeExample.java:55,經過處理後,就方便我們查詢問題了。報告的訂閱線還應回溯和分組,以便進行崩潰報告。

2.2 其他配置

RxDogTag有一個替代的RxDogTag.builder()API,以方便新增配置,例如註釋控制、stacktrace元素位置等等。

Custom handlers 如果自定義觀察者可能修飾了其他觀察者型別,則可以通過ObserverHandler介面將此資訊傳遞給RxDogTag。此介面可用於展開這些自定義觀察者,以顯示其代理及其潛在行為。通過接受處理程式的RxDogTag.Builder#addObserverHandlers(...)過載來安裝這些。

Ignored packages 在檢查堆疊跟蹤以推斷訂閱點時,RxDogTag需要忽略某些包(例如它自己的或RxJava的包)。您可以通過RxDogTag.Builder#addIgnoredPackages(...)新增其他自定義的。

AutoDispose support AutoDispose是一個用於自動處理流的庫,它通過自己的裝飾觀察器進行工作。AutoDispose可以通過其在AutoDisposingObserver介面上的delegateObserver() api與RxDogTag一起工作。使用AutoDispose需要新增如下依賴。

//RxJava 2 implementation("com.uber.rxdogtag:rxdogtag-autodispose:x.y.z") //RxJava 3 implementation("com.uber.rxdogtag2:rxdogtag-autodispose:x.y.z")

通過單獨的rxdogtag-autodispose工件及其AutoDisposeObserverHandler單例例項可以獲得對這一點的支援。

RxDogTag.builder() .configureWith(AutoDisposeConfigurer::configure) .install();

參考:https://github.com/uber/RxDogTag