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)。
 

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

  • 流水线是“被观察者”,
  • 流动着的手机是“数据流”,
  • 打包员是“观察者”,
  • 观察的事件是“手机毛坯进入流水线”,
  • 观察者的响应动作是“将没有问题的手机打包好,有问题的手机另行处理”,
  • 订阅是“事件发生以后响铃通知”。
  • 至于加工工人,只是在观察者的响应动作发生前对数据流的处理。
      
      
    (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<Phone, Phone>() {            //装天线加工
                    @Override
                    public Phone call(Phone phone) {
                        try {
                            Thread.sleep(2000);  
                            //为了体现顺序,我给加工设置了耗时
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        return phone.change("装了天线的");
                    }
                })
                .map(new Func1<Phone, Phone>() {            //装摄像头加工
                    @Override
                    public Phone call(Phone phone) {
                        return phone.change("装了摄像头的、");
                    }
                })
                .subscribe(new Observer<Phone>() {          //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<T, R> extends Function {
    R call(T t);
}

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

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

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

 .map(new Func1<Phone, Phone>() {            //装摄像头加工
                    @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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容

  • 文章转自:http://gank.io/post/560e15be2dca930e00da1083作者:扔物线在正...
    xpengb阅读 7,019评论 9 73
  • 前言我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard...
    占导zqq阅读 9,158评论 6 151
  • 我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的...
    Jason_andy阅读 5,456评论 7 62
  • 以下都是本人收集和总结的内容: 1. 什么是Rxjava Rx含义 ReactiveX是Reactive Exte...
    WuXiao_阅读 4,153评论 0 9
  • 前言 终究没有经受住RxJava的诱惑,只恨自己来的比较晚,走起~ RxJava 是什么? 一个在 Java VM...
    王永迪阅读 4,270评论 3 37