RxJava+Retrofit (二) 观察者模式及Rx基础概念解释

本系列的七篇文章(目前完成进度:2/7):
1、什么响应式编程
2、观察者模式及Rx基础概念解释
3、RxJava深入浅出
4、RxJava+Retrofit 的结合
5、RxJava的高阶使用
6、Retrofit的进阶应用
7、总结

观察者模式

其实非常简单,就是监听。我们在做Android开发的时候,必定绕不过的就是给Button设置监听器(你没做过算我输好吧):

 bn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d("TAG","OnCLick");
            }
        });

在上面的例子中,匿名内部类View.OnClickListener就是观察者,按钮bn就是被观察者。一旦被观察者被观察到“被点击”这个事件,观察者就会做出相应的反应(出log)。
 

RxJava+Retrofit (二) 观察者模式及Rx基础概念解释_第1张图片
 
  
  是的,你已经用了很久的观察者模式了,只是你不知道而已。
  观察者模式的描述应该是这样的:定义一个被观察对象,再定义一个(或多个)观察者,观察者时刻在观察着被观察对象的一举一动, 一旦被观察对象的状态发生了变化,所有的观察者都会马上做出反应。
  
  
  补充一点,在现实的编程中不会有“时刻都在观察”这种这么蠢的实现方式的,所以最好不要将观察者模式理解为'观察者'时刻监控着'被观察者'(虽然语义上这样的),应该理解为:'被观察者'其实是‘通知者’,自己有点什么状态变化(或者是什么事情发生)就马上通知"观察者"(就是实现约定好的),然后观察者再对此做出反应。(所以我个人更倾向于将“观察者模式”称为“通知者模式”)
  
  
  
  回到本系列的第一篇,那个和全蛋一起工作的你。流水线模式是观察者模式吗,是吗?是的。但是,请注意,只有最后的打包员才是观察者!!!你们这些加工工人并不算是观察者,就算是观察者,地位也是比打包员的低的!(此处我是后来才意识到的,因而算是一个错误)
  为什么这样说,其实大家可以理解为打包员才是可以睡懒觉的人,当然在加工工人没事做的时候也是在睡懒觉。但是,就算你们都是在睡懒觉,打包员才是“观察者”,当手机开始在流水线上流动的时候,流水线只会通知打包员,打包员一醒,就会把你们这些加工工人 全部叫醒,帮他干活。(需要感受一下打包员和加工工人地位的差距,以及唤醒的时机)
  
  现在再理一下思路:

  • 流水线是“被观察者”,
  • 流动着的手机是“数据流”,
  • 打包员是“观察者”,
  • 观察的事件是“手机毛坯进入流水线”,
  • 观察者的响应动作是“将没有问题的手机打包好,有问题的手机另行处理”,
  • 订阅是“事件发生以后响铃通知”。
  • 至于加工工人,只是在观察者的响应动作发生前对数据流的处理。
      
      
    (Ps,将“被观察者”换为“通知者”真的是会舒服很多)

用RxJava做个小Demo

例子还是我们的手机加工,废话不多说,直接上代码:

static void product() {
        Phone[] phones = new Phone[5];
        for (int i = 0; i < phones.length; i++) {
            phones[i] = new Phone(i + "号iPhone");
        }

        Observable.from(phones)                             //Observable,被观察者
                .map(new Func1() {            //装天线加工
                    @Override
                    public Phone call(Phone phone) {
                        try {
                            Thread.sleep(2000);  
                            //为了体现顺序,我给加工设置了耗时
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        return phone.change("装了天线的");
                    }
                })
                .map(new Func1() {            //装摄像头加工
                    @Override
                    public Phone call(Phone phone) {
                        return phone.change("装了摄像头的、");
                    }
                })
                .subscribe(new Observer() {          //Observer,观察者订阅事件
                    @Override
                    public void onCompleted() {
                        System.out.println("搞掂,收工!");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println("出了点小问题");
                    }

                    @Override
                    public void onNext(Phone phone) {
                        System.out.println(phone.show()+"被打包好了");
                    }
                });
    }

输出结果是:

装了摄像头的、装了天线的0号iPhone被打包好了
装了摄像头的、装了天线的1号iPhone被打包好了
装了摄像头的、装了天线的2号iPhone被打包好了
装了摄像头的、装了天线的3号iPhone被打包好了
装了摄像头的、装了天线的4号iPhone被打包好了
搞掂,收工!

Process finished with exit code 0

//附,这里的输出是每两秒输出一次

代码我放到Gist了,赏脸给个star可好.

RxJava的基本概念

Observable:被观察者,也可解释为发射源,或数据流就是从这里发射出来的;

Observer:观察者,接收源,数据流就是在这里被接收;

Subscriber:“订阅者”,也是接收源,那它跟Observer有什么区别呢?Subscriber实现了Observer接口,比Observer多了一个最重要的方法unsubscribe( ),用来取消订阅,当你不再想接收数据了,可以调用unsubscribe( )方法停止接收,Observer 在 subscribe() 过程中,最终也会被转换成 Subscriber 对象,一般情况下,建议使用Subscriber作为接收源;

Subscription:Observable调用subscribe( )方法返回的对象,同样有unsubscribe( )方法,可以用来取消订阅事件;

Action0:RxJava中的一个接口,它只有一个无参call()方法,且无返回值,同样还有Action1,Action2...Action9等,Action1封装了含有 1 个参的call()方法,即call(T t),Action2封装了含有 2 个参数的call方法,即call(T1 t1,T2 t2),以此类推;

Func0:与Action0非常相似,也有call()方法,但是它是有返回值的,同样也有Func0、Func1...Func9;

关于Action 和 Func:

先说Func吧,在上面的demo中,我们用到了Func1,于是我们去看看Func1的源码:

/**
 * Represents a function with one argument.
 */
public interface Func1 extends Function {
    R call(T t);
}

非常短吧,只有一个方法call(T t),再跑去看看Func2的源码:

/**
 * Represents a function with two arguments.
 */
public interface Func2 extends Function {
    R call(T1 t1, T2 t2);
}

同样的,也是只有一个方法,call(T1 t1,T2 t2)。
再看回我们的Demo:

 .map(new Func1() {            //装摄像头加工
                    @Override
                    public Phone call(Phone phone) {
                        return phone.change("装了摄像头的、");
                    }
                })

在这里,我们想要做的是“给手机装摄像头”,我们的预期是我们提供一个方法给你,你只需要把“还没装摄像头的手机”当作是一个参数输入到这个方法里面,然后这个方法就会返回“装了摄像头的手机”。 (很明显,这段话的“你”指的是Rx框架)
  然而,在Java中是没有方法指针这种东西,为了达到“将指定方法传递给Rx框架”的目的,设计者设计了Func和Action。
  我们通过传递Func实例来传递一个方法!首先我们先新建一个Func1实例,然后将我们想要执行的方法写到Func1实例中的call方法中(覆盖),最后再把这个实例传递给Rx框架。Rx框架就会在指定的时刻执行我们Func1实例中的call方法,并把call方法的返回值传递到下一个流程。
  
  大概就是这样了,通过传递实例来传递方法在Java中其实不少见,最常见的就是给Button传递一个OnClickListener来传递回调方法。
  此外,我们在使用Func有时可能不止需要一个输入,可能要0个输入就好了,但有时需要可能需要2个、3个...输入的话,那该如何。
  诸君莫方,我们还有Func0、Func1、Func2...肯定有一款适合你。Func后面的数字表示的是call方法的参数个数,我们只要根据需要选择Func接口就可以了(可看上面的两个Func接口的源码,比较出差别)。
  
  
  说完Func,Action也就差不多了,Action和Func的区别就在于,Action没有返回值。

最后

似乎也没有什么好总结的了,就这样了吧。


Reference:http://www.jianshu.com/p/5e93c9101dc5

未经授权,禁止转载
原文地址:http://www.jianshu.com/p/b1bd50afb071

你可能感兴趣的:(RxJava+Retrofit (二) 观察者模式及Rx基础概念解释)