エラー処理
これ
onError()
onComplete()
や
onError()
などの
Observable
メソッドを完全に無視しました。 これらのメソッドは、
Observable
が新しいデータの生成を停止したときに、それ以上生成するものがないか、エラーが発生したために呼び出されます。
最初の
Subscriber
onCompleted()
および
onError()
監視し
onCompleted()
。 これらのポイントで何か役に立つことをしましょう:
Observable.just("Hello, world!") .map(s -> potentialException(s)) .map(s -> anotherPotentialException(s)) .subscribe(new Subscriber<String>() { @Override public void onNext(String s) { System.out.println(s); } @Override public void onCompleted() { System.out.println("Completed!"); } @Override public void onError(Throwable e) { System.out.println("Ouch!"); } });
potentialException()
および
anotherPotentialException()
が実行時に例外をスローできるとします。 各
Observable
は、
onCompleted()
または
onError
呼び出して実行を完了します。 この場合、プログラムの出力は文字列の後に「Completed!」が続くか、出力が単一の「Ouch!」で構成されます(例外がスローされたため)。
したがって、いくつかの結論があります。
-
onError()
は、例外がいつスローされたかに関係なく発生します。
これにより、エラー処理が非常に簡単になります。最後にある1つの関数で発生する各エラーを簡単に処理できます。 - オペレーターは例外を処理する必要はありません。
Observables
チェーンのどこかで発生するエラーの処理は、次のようにSubscriber
タスクになります。 各例外はonError()
直接続きます。 -
Subscriber
が新しいアイテムの受信を停止したことはいつでもわかります。
いつシャットダウンするかを知ることで、より一貫性のあるコードを書くことができます(ただし、Observable
が完了しないこともあります)。
エラー処理に対するこのアプローチは、従来のアプローチよりもはるかに簡単だと思います。 コールバック関数を使用してコードを記述している場合、それぞれでエラー処理が発生するはずです。 これは、コードが多くの場所で繰り返され始めるという事実につながるだけでなく、 各コールバック関数がエラーの処理方法を認識しなければならないという事実につながります。
RxJavaの場合、
Observable
はエラーの処理方法さえ知らないはずです! これは演算子にも適用されます。前の段階のいくつかで重大なエラーが発生した場合、それらは実行されません。 すべてのエラー処理は
Subscriber
ます。
プランナー
ネットワークへのリクエストを行うAndroidアプリケーションがあります。 リクエストには時間がかかる場合があるため、別のスレッドに移動します。 あなたには、あなたがどのように問題を抱えているかを振り返る時間すらありません。
マルチスレッドAndroidアプリケーションは、正しいスレッドで正しいコードを実行することを確認する必要があるため、作成が困難です。 何かを混乱させると、アプリケーションがクラッシュします。 典型的な例は、メインスレッドからではなく、
View
ステートを変更しようとしたことに応じて発生する例外です。
RxJavaでは、それぞれ
subscribeOn()
と
observeOn()
を使用して、
Observer
と
Subscriber
を起動するスレッドを簡単に指定できます。
myObservableServices.retrieveImage(url) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(bitmap -> myImageView.setImageBitmap(bitmap));
ちょうどいい?
Subscriber
が別のI / Oストリームで実行される前に行われるすべての処理、および
View
を使用した操作は、メインストリーム1で既に機能しています。
ここで興味深いのは、
subscribeOn()
と
observeOn()
は、単なる
Observable
で呼び出すことができるということです。
Observable()
動作やそれに続く演算子を心配する必要はありません-必要なスレッドでタスクの実行を分散させるために、最後に
subscribeOn()
と
observeOn()
を追加するだけです。
AsyncTask
などを使用する場合は、どの部分を並列に実行するかを考慮してコードを記述する必要があります。 RxJavaの場合、単純にコードを記述し、それを実行する場所を示します2 。
サブスクリプション
私はまだあなたから隠れている1つのポイントがあります。
Observable.subscribe()
を呼び出すと、
Observable
と
Subscriber
接続である
Subscription
クラスのオブジェクトが返されます。
Subscription subscription = Observable.just("Hello, World!") .subscribe(s -> System.out.println(s));
将来、
Subscription
を終了するには、受け取った
Subscription
を使用できます。
subscription.unsubscribe(); System.out.println("Unsubscribed=" + subscription.isUnsubscribed()); // "Unsubscribed=true"
サブスクリプションをキャンセルすると、RxJavaは記述したチェーン全体を停止します。つまり、多くの演算子で構成される大きな変換チェーンを記述した場合、unsubscribeは現在実行中のコードに関係なく実行を停止します。 3これ以上は必要ありません。
おわりに
この一連の記事は、RxJavaの紹介にすぎないことに注意してください。 私の紹介があなたにとって花のように見えるのと比較して、興味深い複雑な資料がたくさんあります(信じられない- 背圧について読んでください)。 私はどこでもリアクティブなコードを書くつもりはありませんが、シンプルで理解可能な方法で書き直したいコードのより複雑なセクションのためにそれを保存します。
最初は3つの記事で十分だと思っていましたが、多くの人がAndroidでRxJavaを使用するいくつかの実用的な例を示すように頼み、別の記事を書きました 。 このすばらしいフレームワークを試してみるよう説得するのに、私の紹介が十分であったことを願っています。 調査をさらに深く掘り下げたい場合は、公式wikiページを読むことをお勧めします 。 そして、覚えておいてください: 不可能は存在しません 。
エラーと不正確さについてこの記事を読んでくれたすべての人々に感謝します: MatthiasKäppler 、 Matthew Wear 、 Ulysses Popple 、 Hamid Palo 、 Joel Drotos (あごひげだけで見てください)。
1これは、
Subscriber
を可能な限り軽量にする必要がある理由の1つです。つまり、メインスレッドを必要以上にブロックしないようにするためです。
2ときどき、
observeOn()
および
subscribeOn()
の使用の真実が
observeOn()
れる場合があります。 たとえば、
Observable
が長期間機能すると約束した場合でも、
Subscriber
はI / Oストリームで実行されますが、後者を新しいストリームに転送する理由はありません。
3 最初の部分で、
Observable.just()
は
onNext()
および
onCompleted()
呼び出す
Observable
と同じではないことに気付きました。 そしてポイントはサブスクリプションにあります
onNext()
場合、
onNext()
呼び出す前に、
Subscriber
がまだ署名されているかどうかをチェックします。