RxJava学习 - 13. Transformers and Custom Operators

可以使用compose()和lift()实现自己的operators。Observable和Flowable都有这两个方法。

Transformers

有时候,可能想重新使用Observable或者Flowable链的某个片段,可以使用某种方法,把这些operators组合成新的operators。
ObservableTransformer和FlowableTransformer提供了重新使用代码的能力。

ObservableTransformer

以前有个例子,使用collect()把Observable转成Single<ImmutableList>。看下面的例子:

import com.google.common.collect.ImmutableList;
import io.reactivex.Observable;

public class Launcher {
    public static void main(String[] args) {
        Observable.just("Alpha", "Beta", "Gamma", "Delta", "Epsilon")
                .collect(ImmutableList::builder, ImmutableList.Builder::add)
                .map(ImmutableList.Builder::build)
                .subscribe(System.out::println);
        Observable.range(1, 15)
                .collect(ImmutableList::builder, ImmutableList.Builder::add)
                .map(ImmutableList.Builder::build)
                .subscribe(System.out::println);        
    }
}

下面的代码出现了两次:

collect(ImmutableList::builder, ImmutableList.Builder::add)
        .map(ImmutableList.Builder::build)

我们可以想办法把他们组合成新的operator。对于目标Observable,你可以实现ObservableTransformer<T, R>。这个类有一个apply()方法,接受一个Observable,返回一个Observable。在你的实现里,你可以返回一个Observable链,把任何operators加给上游,然后返回Observable。
对我们的例子,要把Observable转换成Observable<ImmutableList>。我们包装一个ObservableTransformer<T, ImmutableList>:

    public static <T> ObservableTransformer<T, ImmutableList<T>> toImmutableList() {
        return new ObservableTransformer<T, ImmutableList<T>>() {
            @Override
            public ObservableSource<ImmutableList<T>> apply(Observable<T> upstream) {
                return upstream.collect(ImmutableList::<T>builder, ImmutableList.Builder::add)
                        .map(ImmutableList.Builder::build)
                        .toObservable(); // must turn Single into Observable
            }
        };
    }

因为collect()返回一个Single,我们调用toObservable()(因为ObservableTransformer期待一个Observable,而不是Single)。
ObservableTransformer只有一个抽象方法,所以可以使用lambda:

    public static <T> ObservableTransformer<T, ImmutableList<T>> toImmutableList() {
        return upstream -> upstream.collect(ImmutableList::<T>builder, ImmutableList.Builder::add)
                        .map(ImmutableList.Builder::build)
                        .toObservable(); // must turn Single into Observable
    }

想在一个Observable链内调用Transformer,可以使用compose()方法。它接受一个ObservableTransformer<T, R>,返回转换后的Observable:

import com.google.common.collect.ImmutableList;
import io.reactivex.Observable;
import io.reactivex.ObservableTransformer;

public class Launcher {
    public static void main(String[] args) {
        Observable.just("Alpha", "Beta", "Gamma", "Delta", "Epsilon")
                .compose(toImmutableList())
                .subscribe(System.out::println);
        Observable.range(1, 10)
                .compose(toImmutableList())
                .subscribe(System.out::println);     
    }
    
    public static <T> ObservableTransformer<T, ImmutableList<T>> toImmutableList() {
        return upstream -> upstream.collect(ImmutableList::<T>builder, ImmutableList.Builder::add)
                        .map(ImmutableList.Builder::build)
                        .toObservable(); // must turn Single into Observable
    }    
}

你也可以为特定的emission类型和接受的参数增加Transformers。例如,增加一个joinToString(),它接受一个分隔符,用来级联字符串:

import io.reactivex.Observable;
import io.reactivex.ObservableTransformer;

public class Launcher {
    public static void main(String[] args) {
        Observable.just("Alpha", "Beta", "Gamma", "Delta", "Epsilon")
                .compose(joinToString("/"))
                .subscribe(System.out::println);      
    }
    
    public static ObservableTransformer<String, String> joinToString(String separator) {
        return upstream -> upstream
                .collect(StringBuilder::new, (b,s) -> {
                    if (b.length() == 0)
                        b.append(s);
                    else
                        b.append(separator).append(s);
                })
                .map(StringBuilder::toString)
                .toObservable();
    }    
}

FlowableTransformer

当你实现ObservableTransformer的时候,也许觉得增加FlowableTransformer会更好。这样,你的operator可用于Observables,也可用于Flowables。
FlowableTransformer和ObservableTransformer差别不大。当然,和Flowables组合时,它支持背压:

扫描二维码关注公众号,回复: 4468758 查看本文章
import com.google.common.collect.ImmutableList;
import io.reactivex.Flowable;
import io.reactivex.FlowableTransformer;

public class Launcher {
    public static void main(String[] args) {
        Flowable.just("Alpha", "Beta", "Gamma", "Delta", "Epsilon")
                .compose(toImmutableList())
                .subscribe(System.out::println);
        Flowable.range(1, 10)
                .compose(toImmutableList())
                .subscribe(System.out::println);     
    }
    
    public static <T> FlowableTransformer<T, ImmutableList<T>> toImmutableList() {
        return upstream -> upstream.collect(ImmutableList::<T>builder, ImmutableList.Builder::add)
                        .map(ImmutableList.Builder::build)
                        .toFlowable(); // must turn Single into Observable
    }    
}

Avoiding shared state with Transformers

比如,你想增加一个ObservableTransformer<T, IndexedValue>,它把每个emission和一个从0开始的连续索引配对。首先,你增加一个IndexedValue类:

    static final class IndexedValue<T> {
        final int index;
        final T value;
        IndexedValue(int index, T value) {
            this.index = index;
            this.value = value;
        }
        @Override
        public String toString() {
            return index + " - " + value;
        }
    }

然后,你增加一个ObservableTransformer<T, IndexedValue>,使用一个AtomicInteger做索引:

    static <T> ObservableTransformer<T,IndexedValue<T>> withIndex() {
        final AtomicInteger indexer = new AtomicInteger(-1);
        return upstream -> upstream.map(v -> new IndexedValue<T>(indexer.incrementAndGet(), v));
    }

看出问题了吗?让我们运行下面的程序。仔细看输出:

import io.reactivex.Observable;
import io.reactivex.ObservableTransformer;
import java.util.concurrent.atomic.AtomicInteger;

public class Launcher {
    public static void main(String[] args) {
        Observable<IndexedValue<String>> indexedStrings =
                Observable.just("Alpha", "Beta", "Gamma", "Delta", "Epsilon")
                .compose(withIndex());
        indexedStrings.subscribe(v -> System.out.println("Subscriber 1: " + v));
        indexedStrings.subscribe(v -> System.out.println("Subscriber 2: " + v));        
    }
    
    static <T> ObservableTransformer<T,IndexedValue<T>> withIndex() {
        final AtomicInteger indexer = new AtomicInteger(-1);
        return upstream -> upstream.map(v -> new IndexedValue<T>(indexer.incrementAndGet(), v));
    }
    
    static final class IndexedValue<T> {
        final int index;
        final T value;
        IndexedValue(int index, T value) {
            this.index = index;
            this.value = value;
        }
        @Override
        public String toString() {
            return index + " - " + value;
        }
    }    
}

输出是

Subscriber 1: 0 - Alpha
Subscriber 1: 1 - Beta
Subscriber 1: 2 - Gamma
Subscriber 1: 3 - Delta
Subscriber 1: 4 - Epsilon
Subscriber 2: 5 - Alpha
Subscriber 2: 6 - Beta
Subscriber 2: 7 - Gamma
Subscriber 2: 8 - Delta
Subscriber 2: 9 - Epsilon

注意,AtomicInteger的一个实例被两个订阅共享了。
可以为每个订阅增加一个资源(比如AtomicInteger),包装在Observable.defer()内:

    static <T> ObservableTransformer<T,IndexedValue<T>> withIndex() {
        return upstream -> Observable.defer(() -> {
            AtomicInteger indexer = new AtomicInteger(-1);
            return upstream.map(v -> new IndexedValue<T>(indexer.incrementAndGet(), v));
        });
    }

对于这个例子,也可以使用Observable.zip()或者zipWith(),解决我们的问题:

    static <T> ObservableTransformer<T,IndexedValue<T>> withIndex() {
        return upstream ->
            Observable.zip(upstream,
                Observable.range(0,Integer.MAX_VALUE),
                (v,i) -> new IndexedValue<T>(i, v)
        );
    }

Operators

理想的情况下,你很少需要从头开始通过实现ObservableOperator和FlowableOperator构造自己的operator。ObservableTransformer和FlowableTransformer可以满足大多数需求。
可有时候,你发现不得不做些现有的operators不能做或者不容易做的事情。排除了任何选项,你可能不得不增加一个operator,在上游和下游之间操纵每个onNext()、onComplete()和onError()事件。
在你增加自己的operator之前,要先试试compose()。如果失败了,推荐你在StackOverflow提问题。
实在不行,再构造自己的operator。

Implementing an ObservableOperator

实现自己的ObservableOperator(或者FlowableTransformer)要做更多的工作。不组合现有的operators,你需要拦截onNext()、onComplete()、onError()和onSubscribe(),实现自己的Observer。该Observer把onNext()、onComplete()和onError()事件传给下游Observer。
比如,你要增加doOnEmpty() operator,当onComplete()被调用的时候,它会执行一个Action。要增加自己的ObservableOperator<Downstream, Upstream>,需要实现它的apply()方法。它接受一个Observer,返回一个Observer。然后,你可以通过调用lift(),使用这个ObservableOperator:

import io.reactivex.Observable;
import io.reactivex.ObservableOperator;
import io.reactivex.Observer;
import io.reactivex.functions.Action;
import io.reactivex.observers.DisposableObserver;

public class Launcher {
    public static void main(String[] args) {
        Observable.range(1, 5)
                .lift(doOnEmpty(() -> System.out.println("Operation 1 Empty!")))
                .subscribe(v -> System.out.println("Operation 1: " + v));
        Observable.<Integer>empty()
                .lift(doOnEmpty(() -> System.out.println("Operation 2 Empty!")))
                .subscribe(v -> System.out.println("Operation 2: " + v));        
    }
    
    public static <T> ObservableOperator<T, T> doOnEmpty(Action action) {
        return new ObservableOperator<T, T>() {
            @Override
            public Observer<? super T> apply(Observer<? super T> observer) throws Exception {
                return new DisposableObserver<T>() {
                    boolean isEmpty = true;

                    @Override
                    public void onNext(T value) {
                        isEmpty = false;
                        observer.onNext(value);
                    }

                    @Override
                    public void onError(Throwable t) {
                        observer.onError(t);
                    }

                    @Override
                    public void onComplete() {
                        if (isEmpty) {
                            try {
                                action.run();
                            } catch (Exception e) {
                                onError(e);
                                return;
                            }
                        }
                        observer.onComplete();
                    }
                };
            }
        };
    }    
}

就像Transformers一样,当增加自己的operators的时候,不要在订阅之间共享状态。
还有,onNext()、onComplete()和onError()调用是可以按需要操纵和混合的。比如,toList()不会把收到的每个onNext()都传给下游。它会在内部列表中收集这些emissions。当上游调用了onComplete(),它就调用下游的onNext(),把列表传给下游,然后调用onComplete()。现在,我们实现自己的myToList(),来理解toList()如何工作:

import io.reactivex.Observable;
import io.reactivex.ObservableOperator;
import io.reactivex.observers.DisposableObserver;
import java.util.ArrayList;
import java.util.List;

public class Launcher {
    public static void main(String[] args) {
        Observable.range(1, 5)
                .lift(myToList())
                .subscribe(v -> System.out.println("Operation 1: " + v));
        Observable.<Integer>empty()
                .lift(myToList())
                .subscribe(v -> System.out.println("Operation 2: " + v));        
    }
    
    public static <T> ObservableOperator<List<T>,T> myToList() {
        return observer -> new DisposableObserver<T>() {
            ArrayList<T> list = new ArrayList<>();
            @Override
            public void onNext(T value) {
                //add to List, but don't pass anything downstream
                list.add(value);
            }
            @Override
            public void onError(Throwable t) {
                observer.onError(t);
            }
            @Override
            public void onComplete() {
                observer.onNext(list); //push List downstream
                observer.onComplete();
            }
        };
    }    
}

Custom Transformers and operators for Singles, Maybes, and Completables

当你想增加一个Observable或者Flowable operator来产生Single,你可能发现是很容易的(使用SingleTransformer或者SingleOperator)。对Maybe(使用MaybeTransformer或者MaybeOperator)和Completable(CompletableTransformer或者CompletableOperator)也是如此。
下面是SingleTransformer的例子,接受Single<Collection>映射到一个不可变的集合:

import io.reactivex.Observable;
import io.reactivex.SingleTransformer;
import java.util.Collection;
import java.util.Collections;

public class Launcher {
    public static void main(String[] args) {
        Observable.just("Alpha", "Beta", "Gamma", "Delta", "Epsilon")
            .toList()
            .compose(toUnmodifiable())
            .subscribe(System.out::println);
    }
    
    public static <T> SingleTransformer<Collection<T>, Collection<T>> toUnmodifiable() {
        return singleObserver -> singleObserver.map(Collections::unmodifiableCollection);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43364172/article/details/84317783