【Programming】RxJava リアクティブプログラミング vol.3 / RxJavaの構成~前編~

in #promari5 years ago (edited)

o1AJ9qDyyJNSpZWhUgGYc3MngFqoAMxopALi6Zh4C8ck3F7cr.png

<p dir="auto">前回は<a href="https://github.com/ReactiveX/RxJava" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">RxJavaの概要についてまとめました(記事は<a href="https://steemit.com/promari/@promari/programming-rxjava-vol-2-rxjava" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">こちら)。今回はRxJavaの構成をまとめてみます。 <h3>1.4 RxJavaの構成 <h4>1.4.1 Flowable/Observable <ul> <li><p dir="auto">FlowableおよびObservableはデータを生産し通知するクラス <li><p dir="auto">FlowableとObservableの違いは、Flowableがバックプレッシャーの機能があり、Observableにはない <li><p dir="auto">Flowable/Observableは基本的にReactive Streamsのルールおよびそのルールに影響を与えたObservable契約に従わないと正しくデータが通知されることが保証されない。 <li><p dir="auto">通知する際のルールは以下のものがある。 <ul> <li>nullを通知してはならない <li>データの通知は行っても行わなくてもよい <li>Flowable/Observableの処理を終了する際は完了かエラーの通知のどちらか一方を行わないといけない。両方を通知することはない <li>完了かエラーの通知をした後は他の通知を行ってはいけない <li>通知をする際は1つずつ順番に行い同時に行ってはいけない <li><p dir="auto">※nullを通知してはならないというルールはRxJava 2.xからのルールでRxJava 1.xではnullを通知することは可能なので注意する。 <li><p dir="auto">※データの生成を複数スレッドから行う場合はそもそもの設計を見直すか、1つのスレッド上で処理を行うFlowable/Observableを複数用意し、それらを1つに結合するメソッドを使うなどして処理を行う。 <p dir="auto"><img src="https://images.hive.blog/768x0/https://img.esteem.ws/6hc412jg7i.png" alt="6hc412jg7i.png" srcset="https://images.hive.blog/768x0/https://img.esteem.ws/6hc412jg7i.png 1x, https://images.hive.blog/1536x0/https://img.esteem.ws/6hc412jg7i.png 2x" /> <h4>Source:<a href="https://www.amazon.co.jp/dp/B06XGYSHCN/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">RxJavaリアクティブプログラミング <ul> <li>参考サイト <ul> <li><a href="https://github.com/reactive-streams/reactive-streams-jvm/blob/master/README.md" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">reactive-streams-jvm/README.md <li><a href="http://reactivex.io/documentation/contract.html" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Observable契約 <h4>1.4.2 Subscriber/Observer <ul> <li><p dir="auto">SubscriberおよびObserverは通知されたデータを受け取りそのデータを使った処理を行うインターフェース <li><p dir="auto">Subscriberはバックプレッシャーの機能があり通知するデータ数をリクエストしないといけないのに対し、Observerはバックプレッシャーの機能がないため、データ数の制限なしにデータが通知される <li><p dir="auto">Subscriber/Observerのメソッドが呼ばれる順は以下の通り。 <ul> <li>(1) onSubscribeメソッド <li>(2) onNextメソッド <li>(3) onCompleteメソッド <li><p dir="auto">Subscriber/Observerが購読しFlowable/Observableの通知の準備ができたら、onSubscribeメソッドが呼ばれる。このonSubscribeメソッドは1つの購読で1度しか呼ばれない。 <li><p dir="auto">データが通知されるたびにonNextメソッドが呼ばれる。複数のデータが通知される場合はその分だけonNextメソッドが呼ばれ、1件もデータが通知されない場合は1度もonNextメソッドが呼ばれない。 <li><p dir="auto">onNextメソッドは安全な通知を行う。Flowable/Observableからデータを受け取っている限り、onNextメソッドが同時に実行されることはない。 <li><p dir="auto">全てのデータを通知し終えたら、これ以上データを通知することがないことを知らせるためにonCompleteメソッドが呼ばれ、完了時の処理を行う。 <li><p dir="auto">Flowable/Observableの処理中にエラーが発生したらonErrorメソッドが呼ばれ、処理を終了する。 <li><p dir="auto">各メソッドは1つずつ順番に実行されるが、SubscriberのonSubscribeメソッドだけは例外的に処理の途中でonNextメソッドやonCompleteメソッドが実行される。これはonSubscribeメソッドでSubscriptionのrequestメソッドを呼ぶとFlowableがデータの通知を始めてしまうから。 <li><p dir="auto">SubscriberのonSubscribeメソッド内でSubscriptionのrequestメソッドを呼び出すと通知処理が始まってしまうため、もしonSubscribeメソッド内で初期化処理などがある場合は、Subscriptionのrequestメソッドを呼ぶ前に行う必要がある。 <h4>1.4.3 Subscription <ul> <li>SubscriptionはReactive Streamsで定義されているインターフェース <li>通知するデータの数をリクエストするrequestメソッドと処理の途中でも購読を解除するcancelメソッドを持つ。 <li>SubscriptionはSubscriberのonSubscribeメソッドの引数として渡されるオブジェクトで、指定した数だけのデータを通知するようにFlowableにリクエストしたり、購読を解除したりする機能を持つ。 <pre><code>public interface Subscription { public void request(long n); public void cancel(); } <h4>1.4.4 Disposable <ul> <li>Disposableは購読を解除するためのメソッドを持つインターフェース <li>Disposableは、ObservableとObserver間の購読の際にObservableが購読の準備ができた時点でonSubscribeメソッド経由でObserverに渡されるオブジェクトで、購読を処理の途中でも解除する機能を持つ。 <li>DisposableはObservableとObserver間の購読以外でも使われることがあり、Flowable#subscribe(Subscriber)やObservable#subscribe(Observer)でない購読をするメソッド(subscribeメソッド/subscribeWithメソッド)の戻り値としてDisposableが定義されている。戻り値としてのDisposableは外部から購読の解除を可能とする。 <li>ただし、この購読解除の機能を外部に出すということは、外部から別スレッドで購読解除が行われるリスクが発生する。そのため、関数型インターフェースを引数に取る購読メソッドやDisposableSubscriber/DisposableObserverやResourceSubscriber/ResourceObserverによって返されるRxJavaが用意したDisposableのインスタンスは非同期で購読解除の呼び出しがされても問題ないように対応している。 <li>Disposableは購読解除だけではなくリソースなどの破棄を行うためのインターフェースとしても使用可能。処理が終わる際にリソースなどの破棄をしないといけない場合、その破棄する処理をDisposableのdisposeメソッドに実装する。 <li>FlowableEmitter/ObservableEmitterのsetDisposableメソッドにそのDisposableを設定した場合は完了やエラーおよび購読解除時に、ResourceSubscriber/ResourceObserverのaddメソッドでそのDisposableを追加した場合は、そのResourceSubscriber/ResourceObserverのdisposeメソッドを呼ばれた際にDisposableのdisposeメソッドが呼ばれる。 <pre><code>public interface Disposable { void dispose(); boolean isDisposed(); } <h4>1.4.5 FlowableProcessor/Subject <ul> <li>ProcessorとはReactive Streamsで定義されている生産者(Publisher)と消費者(Subscriber)の両方の機能を持っているインターフェース <li>RxJavaではこのReactive StreamsのProcessorの実装クラスとしてFlowableProcessorを持っている。 <li>RxJavaにはObservableとObserverの構成も存在しており、その構成でProcessorと同じ役割を果たすSubjectが用意されている。 <ul> <li>Processor/Subjectの種類 <div class="table-responsive"><table> <thead> <tr><th style="text-align:left">種類<th style="text-align:left">説明 <tbody> <tr><td style="text-align:left">PublishProcessor/PublishSubject<td style="text-align:left">データを受け取ったタイミングでしか消費者(Subscriber/Observer)にデータを通知しないProcessor/Subject <tr><td style="text-align:left">BehaviorProcessor/BehaviorSubject<td style="text-align:left">消費者を購読した直前のデータをバッファし、そのデータから通知するProcessor/Subject <tr><td style="text-align:left">ReplayProcessor/ReplaySubject<td style="text-align:left">受け取った全てのデータを途中から登録した消費者にも通知するProcessor/Subject <tr><td style="text-align:left">AsyncProcessor/AsyncSubject<td style="text-align:left">データの生成が完了した際に最後に受け取ったデータしか消費者に通知しないProcessor/Subject <tr><td style="text-align:left">UnicastProcessor/UnicastSubject<td style="text-align:left">1つの消費者からしか購読されないProcessor/Subject <h4>1.4.6 DisposableSubscriber/DisposableObserver <ul> <li><p dir="auto">DisposableSubscriber/DisposableObserverはDisposableを実装したSubscriber/Observerの実装クラスで、外部から非同期に購読解除のメソッドを呼ばれても安全に購読解除を実行してくれるクラス <li><p dir="auto">これらのクラスでは、onSubscribeメソッドがfinalメソッドとして実装されており、onSubscribeメソッドで渡されるSubscription/Disposableは隠蔽され直接アクセスできないため、次のメソッドからSubscription/Disposableのメソッドを呼び出す。 <li><p dir="auto">DisposableSubscriber のSubscriptionのメソッドを呼び出すメソッド <ul> <li>request(long): Subscriptionのrequestメソッドを呼び出す <li>dispose(): Subscriptionのcancelメソッドを呼び出す <li><p dir="auto">DisposableObserver のDispose のメソッドを呼び出すメソッド <ul> <li>dispose(): Disposeのdisposeメソッドを呼び出す <li>isDispose(): DisposeのisDisposedメソッドを呼び出す <li><p dir="auto">購読開始時の処理をオーバライドして独自の処理を実装したい場合は、onSubscribeメソッド内で呼ばれているonStartメソッドをオーバライドする。 <li><p dir="auto">DisposableSubscriberで初期化処理を行う場合、先に初期化処理を実行してから親のonStartメソッドを呼ぶこと。onStartメソッドを呼び出し後に、初期化処理を実行すると、初期化処理を呼ぶ前に通知処理が始ってしまうので注意が必要。 <p dir="auto"><img src="https://images.hive.blog/768x0/https://img.esteem.ws/9b42rspyh3.png" alt="9b42rspyh3.png" srcset="https://images.hive.blog/768x0/https://img.esteem.ws/9b42rspyh3.png 1x, https://images.hive.blog/1536x0/https://img.esteem.ws/9b42rspyh3.png 2x" /> <h4>Source:<a href="https://www.amazon.co.jp/dp/B06XGYSHCN/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">RxJavaリアクティブプログラミング <h4>1.4.7 ResourceSubscriber/ResourceObserver <ul> <li>ResourceSubscriber/ResourceObserverhはDisposableを実装したSubscriber/Observerの実装クラスで、外部から非同期に購読解除のメソッドを呼ばれても安全に購読解除を実行してくれるクラス。DisposableSubscriber/DisposableObserverが持つ機能に加え、addメソッドで他のDisposableを格納することができる。 <li>格納されたDisposableはResourceSubscriber/ResourceObserverのdisposeメソッドを呼ぶと、格納しているDisposableのdisposeメソッドも一緒に呼び出す。 <li>完了時やエラー時に自動でdisposeメソッドが呼ばれるわけではない。 <li>ResourceSubscriberで初期化処理を行う場合、DisposableSubscriberと同様に、先に初期化処理を実行してから親のonStartメソッドを呼ぶこと。onStartメソッドを呼び出し後に、初期化処理を実行すると、初期化処理を呼ぶ前に通知処理が始ってしまうので注意が必要。 <p dir="auto"><img src="https://images.hive.blog/768x0/https://img.esteem.ws/k83aze4nv5.png" alt="k83aze4nv5.png" srcset="https://images.hive.blog/768x0/https://img.esteem.ws/k83aze4nv5.png 1x, https://images.hive.blog/1536x0/https://img.esteem.ws/k83aze4nv5.png 2x" /> <h4>Source:<a href="https://www.amazon.co.jp/dp/B06XGYSHCN/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">RxJavaリアクティブプログラミング <p dir="auto">次回は「<a href="https://steemit.com/promari/@promari/programming-rxjava-vol-4-rxjava" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">【Programming】RxJava リアクティブプログラミング vol.3 / RxJavaの構成~後編~」についてまとめてみます。 <p dir="auto"><img src="https://images.hive.blog/768x0/https://img.esteem.ws/t0r78hqbeu.png" alt="t0r78hqbeu.png" srcset="https://images.hive.blog/768x0/https://img.esteem.ws/t0r78hqbeu.png 1x, https://images.hive.blog/1536x0/https://img.esteem.ws/t0r78hqbeu.png 2x" /><br /> written by <a href="https://steemit.com/@tamito0201/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">tamito0201 <p dir="auto">プログラミングとのご縁結びなら<a href="https://www.programming-mariage.jp/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">プロマリへ。 <p dir="auto">オンラインプログラミング学習スクールの<a href="https://www.programming-mariage.jp/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">プロマリは、プログラミングの初学者の皆様を応援しています。プログラミング講師と一緒に面白いアプリを作りませんか。 <p dir="auto"><a href="https://www.programming-mariage.jp" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link"><img src="https://images.hive.blog/768x0/https://img.esteem.ws/btpb5hmlur.png" alt="btpb5hmlur.png" srcset="https://images.hive.blog/768x0/https://img.esteem.ws/btpb5hmlur.png 1x, https://images.hive.blog/1536x0/https://img.esteem.ws/btpb5hmlur.png 2x" /> <p dir="auto">The programming school "<a href="https://www.programming-mariage.jp/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Promari" will help you learn programming. "<a href="https://www.programming-mariage.jp/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Promari" is supporting the first scholars of programming. Let's develop an application with our programming instructor.
Sort:  

Wow nic...

Congratulations @promari! You have completed the following achievement on the Steem blockchain and have been rewarded with new badge(s) :

<table><tr><td><span><img src="https://images.hive.blog/768x0/https://steemitimages.com/60x70/http://steemitboard.com/@promari/voted.png?201904030317" srcset="https://images.hive.blog/768x0/https://steemitimages.com/60x70/http://steemitboard.com/@promari/voted.png?201904030317 1x, https://images.hive.blog/1536x0/https://steemitimages.com/60x70/http://steemitboard.com/@promari/voted.png?201904030317 2x" /><td>You received more than 10000 upvotes. Your next target is to reach 15000 upvotes. <p dir="auto"><sub><em>You can view <a href="https://steemitboard.com/@promari" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">your badges on your Steem Board and compare to others on the <a href="http://steemitboard.com/ranking/index.php?name=promari" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Steem Ranking<br /> <sub><em>If you no longer want to receive notifications, reply to this comment with the word <code>STOP <h6><a href="https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Vote for @Steemitboard as a witness to get one more award and increased upvotes!