RxJava Operator (2) Observable の変換
前回の記事では、Observable を作成するだけでは一部の複雑なシナリオを満たせない可能性があるため、作成したオブジェクトに何らかの種類の Observable をインストールする必要がある可能性があります。監視可能。データを出力するようにルールを変換します。この記事では、Observable を変換する方法を学びましょう
1. Buffer
名前が示すように、Buffer オペレーターがしなければならないことは、データを指定されたサイズにキャッシュし、キャッシュされたデータをセットとして出力することです。下の図に示すように、最初の例ではバッファ サイズを 3 に指定し、3 つのデータを収集した後にデータを送信します。2 番目の図では、必要な回数を指定するスキップ パラメーターを追加します。コレクションが送信されるたびにスキップする場合、図で count を 2 に指定し、skip を 3 に指定すると、3 つのデータごとに 2 つのデータを含むセットが出力されます。 count==skip の場合、同等であることがわかります。最初のケースへ。
バッファは数量ルールだけでなく、時間やその他のルールによってもキャッシュできます。たとえば、以下の 2 つの Observable を作成しました。変換の場合、最初のバッファーは量ごとにキャッシュされ、2 番目のバッファーは時間ごとにキャッシュされます。
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>private Observable<List<Integer>> bufferObserver() {<br /></li><li>return Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9).buffer(2, 3);<br /></li><li>}<br /></li><li><br /></li><li>private Observable<List<Long>> bufferTimeObserver() {<br /></li><li>return Observable.interval(1, TimeUnit.SECONDS).buffer(3, TimeUnit.SECONDS).observeOn(AndroidSchedulers.mainThread());<br /></li><li>}</li></ol>
ログイン後にコピー
購読してください
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>mLButton.setText("buffer");<br /></li><li>mLButton.setOnClickListener(e -> bufferObserver().subscribe(i -> log("buffer:" + i)));<br /></li><li>mRButton.setText("bufferTime");<br /></li><li>mRButton.setOnClickListener(e -> bufferTimeObserver().subscribe(i -> log("bufferTime:" + i)));</li></ol>
ログイン後にコピー
実行結果は次のとおりです。最初の Observable が 3 秒ごとに最初の 2 つの数値を出力し、2 番目の Observable が 3 秒ごとに 2 を出力することがわかります。数字。
2. FlatMap
FlatMap は、データを出力する前に、必要なルールに従ってデータを変換できる多用途の演算子です。原理は、この Observable を、元の Observable によって発行されたデータをソース データとして使用する複数の Observable に変換し、これらの複数の Observable によって発行されたデータを統合して発行することです。最終的な順序は、まとめて発行される場合があることに注意してください。順序に厳密な要件がある場合は、concatmap 演算子を使用できます。 FlatMapIterable は、変換される複数の Observable がソース データとして Iterable を使用することを除いて、FlatMap と同じベースを持っています。
次に、FlatMap と FlatMapIterable を使用して 2 つの Observable を作成し、変換します。
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>private Observable<String> flatMapObserver() {<br /></li><li>return Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9).flatMap(integer -> Observable.just("flat map:" + integer));<br /></li><li>}<br /></li><li><br /></li><li>private Observable<? extends Integer> flatMapIterableObserver() {<br /></li><li>return Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9)<br /></li><li>.flatMapIterable(<br /></li><li>integer -> {<br /></li><li>ArrayList<Integer> s = new ArrayList<>();<br /></li><li>for (int i = 0; i < integer; i++) {<br /></li><li>s.add(integer);<br /></li><li>}<br /></li><li>return s;<br /></li><li>}<br /></li><li>);<br /></li><li>}</li></ol>
ログイン後にコピー
個別に購読してください
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>mLButton.setText("flatMap");<br /></li><li>mLButton.setOnClickListener(e -> flatMapObserver().subscribe(i -> log(i)));<br /></li><li>mRButton.setText("flatMapIterable");<br /></li><li>mRButton.setOnClickListener(e -> flatMapIterableObserver().subscribe(i -> log("flatMapIterable:" + i)));</li></ol>
ログイン後にコピー
実行後の結果は次のとおりです。最初の演算子は出力されたデータにフラット マップ文字列プレフィックスを追加し、2 番目の演算子は出力されたデータにデータを追加します。展開するとn個の数値が出力されます。
3. GroupBy
GroupBy オペレーターは、元の Observable によって出力されたデータをキーに従っていくつかの小さな Observable に分割し、SQL の groupBy と同様に、これらの小さな Observable が含まれるデータを出力します。
使用時には、同じキーを持つすべてのデータが同じ小さな Observable に含まれるようにするためのルールを提供する必要があります。さらに、これらのデータを変換する機能も提供できます。これは、 flatMap を統合するのと同様です。
次に、groupBy で変換された 2 つの Observable オブジェクトを作成します。最初のオブジェクトは奇数と偶数に従ってグループ化され、2 番目のグループ化の後、数値は文字列プレフィックスで追加されます
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>mLButton.setText("groupBy");<br /></li><li>mLButton.setOnClickListener(e -> groupByObserver().subscribe(new Subscriber<GroupedObservable<Integer, Integer>>() {<br /></li><li>@Override<br /></li><li>public void onCompleted() {<br /></li><li><br /></li><li>}<br /></li><li><br /></li><li>@Override<br /></li><li>public void onError(Throwable e) {<br /></li><li><br /></li><li>}<br /></li><li><br /></li><li>@Override<br /></li><li>public void onNext(GroupedObservable<Integer, Integer> groupedObservable) {<br /></li><li>groupedObservable.count().subscribe(integer -> log("key" + groupedObservable.getKey() + " contains:" + integer + " numbers"));<br /></li><li>}<br /></li><li>}));<br /></li><li>mRButton.setText("groupByKeyValue");<br /></li><li>mRButton.setOnClickListener(e -> groupByKeyValueObserver().subscribe(new Subscriber<GroupedObservable<Integer, String>>() {<br /></li><li>@Override<br /></li><li>public void onCompleted() {<br /></li><li><br /></li><li>}<br /></li><li><br /></li><li>@Override<br /></li><li>public void onError(Throwable e) {<br /></li><li><br /></li><li>}<br /></li><li><br /></li><li>@Override<br /></li><li>public void onNext(GroupedObservable<Integer, String> integerIntegerGroupedObservable) {<br /></li><li>if (integerIntegerGroupedObservable.getKey() == 0) {<br /></li><li>integerIntegerGroupedObservable.subscribe(integer -> log(integer));<br /></li><li>}<br /></li><li>}<br /></li><li>}));<br /></li><li>}</li></ol>
ログイン後にコピー
実行結果は次のとおりです。 、望む結果が得られます。
4. Map、Cast
Map オペレーターの機能は FlatMap に似ていますが、FlatMap はいくつかの中間 Observable を必要とするのに対し、違いはデータを直接変換することです。
Cast は、Observable によって出力されたデータを、Map の特定の実装である別の型に強制します
次に、map によって変換された 2 つの Observable オブジェクトを作成し、キャスト
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>private Observable<Integer> mapObserver() {<br /></li><li>return Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9).map(integer -> integer * 10);<br /></li><li>}<br /></li><li><br /></li><li>private Observable<Dog> castObserver() {<br /></li><li>return Observable.just(getAnimal())<br /></li><li>.cast(Dog.class);<br /></li><li>}<br /></li><li><br /></li><li>Animal getAnimal() {<br /></li><li>return new Dog();<br /></li><li>}<br /></li><li><br /></li><li>class Animal {<br /></li><li>protected String name = "Animal";<br /></li><li><br /></li><li>Animal() {<br /></li><li>log("create " + name);<br /></li><li>}<br /></li><li><br /></li><li>String getName() {<br /></li><li>return name;<br /></li><li>}<br /></li><li>}<br /></li><li><br /></li><li>class Dog extends Animal {<br /></li><li>Dog() {<br /></li><li>name = getClass().getSimpleName();<br /></li><li>log("create " + name);<br /></li><li>}<br /></li><li><br /></li><li>}</li></ol>
ログイン後にコピー
でそれらを登録します
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>mLButton.setText("Map");<br /></li><li>mLButton.setOnClickListener(e -> mapObserver().subscribe(i -> log("Map:" + i)));<br /></li><li>mRButton.setText("Cast");<br /></li><li>mRButton.setOnClickListener(e -> castObserver().subscribe(i -> log("Cast:" + i.getName())));</li></ol>
ログイン後にコピー
运行后得到结果如下。可以看到,map操作符将数据都乘以10后再发射出来,cast操作符将Animal类型的对象强制转化为Dog类型的对象。另外我们还可以验证一下一个知识点,有继承的情况下创建对象会首先调用父类的构造方法哦。
五、Scan
Scan操作符对一个序列的数据应用一个函数,并将这个函数的结果发射出去作为下个数据应用这个函数时候的第一个参数使用,有点类似于递归操作
下面我们通过一个存放10个2的list创建一个Observable对象并使用scan对其进行转化,转化的函数就是计算的结果乘以下一个数。
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>private Observable<Integer> scanObserver() {<br /></li><li>return Observable.from(list).scan((x, y) -> x * y).observeOn(AndroidSchedulers.mainThread());<br /></li><li>}</li></ol>
ログイン後にコピー
对其进行订阅
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>mLButton.setText("scan");<br /></li><li>mLButton.setOnClickListener(e -> scanObserver().subscribe(i -> log("scan:" + i)));</li></ol>
ログイン後にコピー
得到结果如下,可以看到,我们输出了2的n次方。
六、Window
Window操作符类似于我们前面讲过的buffer,不同之处在于window发射的是一些小的Observable对象,由这些小的Observable对象来发射内部包含的数据。同buffer一样,window不仅可以通过数目来分组还可以通过时间等规则来分组
下面我们创建两个Observable对象分别使用window的数目和时间规则来进行分组。
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>private Observable<Observable<Integer>> windowCountObserver() {<br /></li><li>return Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9).window(3);<br /></li><li>}<br /></li><li><br /></li><li>private Observable<Observable<Long>> wondowTimeObserver() {<br /></li><li>return Observable.interval(1000, TimeUnit.MILLISECONDS)<br /></li><li>.window(3000, TimeUnit.MILLISECONDS)<br /></li><li>.observeOn(AndroidSchedulers.mainThread());<br /></li><li>}</li></ol>
ログイン後にコピー
分别对其订阅
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css"><li>mLButton.setText("window");<br /></li><li>mLButton.setOnClickListener(e -> windowCountObserver().subscribe(i -> {<br /></li><li>log(i);<br /></li><li>i.subscribe((j -> log("window:" + j)));<br /></li><li>}));<br /></li><li>mRButton.setText("Time");<br /></li><li>mRButton.setOnClickListener(e -> wondowTimeObserver().subscribe(i -> {<br /></li><li>log(i);<br /></li><li>i.observeOn(AndroidSchedulers.mainThread()).subscribe((j -> log("wondowTime:" + j)));<br /></li><li>}));</li></ol>
ログイン後にコピー
运行结果如下,可以看到第一个Observable对象没次发射出一个包含3个数据的小Observable,第二个Observable对象每隔3秒钟发射出一个包含2~4个数据的Observable对象
Transforming操作符是Rxjava强大之处的重要体现,要灵活使用Rxjava掌握Transforming操作符是必不可少的。
本文的demo程序见github:https://github.com/Chaoba/RxJavaDemo
http://www.bkjia.com/PHPjc/1077811.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/1077811.htmlTechArticleRxJava操作符(二)Transforming Observables 在上一篇文章中,我们了解了如何创建Observable,仅仅创建一个Observable可能无法满足一些复杂的场景,...