自定义RxJava Operator

通过写一个自定义的Operator可以更好的理解RxJava中的流式传递机制。
先借用扔物线的给 Android 开发者的 RxJava 详解 中的一段内容:

这些变换虽然功能各有不同,但实质上都是针对事件序列的处理和再发送。而在 RxJava 的内部,它们是基于同一个基础的变换方法: lift(Operator)。首先看一下 lift() 的内部实现(仅核心代码):

// 注意:这不是 lift() 的源码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的核心代码。
// 如果需要看源码,可以去 RxJava 的 GitHub 仓库下载。
public <R> Observable<R> lift(Operator<? extends R, ? super T> operator) {
    return Observable.create(new OnSubscribe<R>() {
        @Override
        public void call(Subscriber subscriber) {
            Subscriber newSubscriber = operator.call(subscriber);
            newSubscriber.onStart();
            onSubscribe.call(newSubscriber);
        }
    });
}

这段代码很有意思:它生成了一个新的 Observable 并返回,而且创建新 Observable 所用的参数 OnSubscribe 的回调方法 call() 中的实现竟然看起来和前面讲过的 Observable.subscribe() 一样!然而它们并不一样哟~不一样的地方关键就在于第二行 onSubscribe.call(subscriber) 中的 onSubscribe 所指代的对象不同(高能预警:接下来的几句话可能会导致身体的严重不适)——

subscribe() 中这句话的 onSubscribe 指的是 Observable 中的 onSubscribe 对象,这个没有问题,但是 lift() 之后的情况就复杂了点。
当含有 lift() 时:
1.lift() 创建了一个 Observable 后,加上之前的原始 Observable,已经有两个 Observable 了;
2.而同样地,新 Observable 里的新 OnSubscribe 加上之前的原始 Observable 中的原始 OnSubscribe,也就有了两个 OnSubscribe;
3.当用户调用经过 lift() 后的 Observable 的 subscribe() 的时候,使用的是 lift() 所返回的新的 Observable ,于是它所触发的 onSubscribe.call(subscriber),也是用的新 Observable 中的新 OnSubscribe,即在 lift() 中生成的那个 OnSubscribe;
4.而这个新 OnSubscribe 的 call() 方法中的 onSubscribe ,就是指的原始 Observable 中的原始 OnSubscribe ,在这个 call() 方法里,新 OnSubscribe 利用 operator.call(subscriber) 生成了一个新的 Subscriber(Operator 就是在这里,通过自己的 call() 方法将新 Subscriber 和原始 Subscriber 进行关联,并插入自己的『变换』代码以实现变换),然后利用这个新 Subscriber 向原始 Observable 进行订阅。
这样就实现了 lift() 过程,有点像一种代理机制,通过事件拦截和处理实现事件序列的变换。

精简掉细节的话,也可以这么说:在 Observable 执行了 lift(Operator) 方法之后,会返回一个新的 Observable,这个新的 Observable 会像一个代理一样,负责接收原始的 Observable 发出的事件,并在处理后发送给 Subscriber。

操作符的目的本质上是将原Observable发射的item进行改变后继续发射。从表现形式上看就是将一个Observable(比如将其称为ob1)转为另一个Observable(比如将其称为ob2),转换后,ob2发射的条目类型(比如称其为t2)与ob1发射的条目类型(比如称其为t1)不相同。如果按照流式的写法,订阅者将订阅ob2发射的t2条目:

ob1.操作符().subscribe(new Subscriber<t2>(){...});

这种流式的写法是如何得到的实现的?其实每一个操作符内部都会执行一个转换操作,把订阅t2的原始订阅者转为一个订阅t1的新订阅者,然后在新订阅者内部将收到的t1条目转为t2条目后传递给原始订阅者。类似的操作如下:

//每一个操作都需要继承在Operator接口
MyOpt implements Operator<t2,t1>{

    @Override
    public Subscriber<? super t1> call(Subscriber<? super t2> 原始订阅者) {
        //生成一个新订阅者
        return new Subscriber<t1>(原始订阅者) {
            @Override
            public void onCompleted() {
                原始订阅者.onCompleted();
            }

            @Override
            public void onError(Throwable e) {
                原始订阅者.onError(e);
            }

            @Override
            public void onNext(t1) {
             t2 = f(t1);//将收到的t1转为t2
                原始订阅者.onNext(t2);
            }
        };
    }

}

通过这个转换就可以实现流式的调用了。
实际写一个简单的示例,将一个发射Integer的Observable转化为发射String的Observable:

public class MyStringOpt implements Observable.Operator<String,Integer>{
    @Override
    public Subscriber<? super Integer> call(Subscriber<? super String> subscriber) {

        return new Subscriber<Integer>(subscriber) {
            @Override
            public void onCompleted() {
                subscriber.onCompleted();
            }

            @Override
            public void onError(Throwable e) {
                subscriber.onError(e);
            }

            @Override
            public void onNext(Integer integer) {
                subscriber.onNext(String.valueOf(integer));
            }
        };
    }
}

自定义操作符MyStringOpt将一个本来订阅String的订阅者要转为订阅Integer的订阅者。
然后利用MyStringOpt实现流式调用:

 Observable<String> ob = Observable.just(1, 2, 3, 4).cast(Integer.class).lift(new MyStringOpt());
 ob.subscribe(v-> System.out.println(v.getClass().getSimpleName()+": "+v));

执行的结果为:

String: 1
String: 2
String: 3
String: 4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值