RxJava入门七问(一)

1. RxJava采用了观察者模式,什么是观察者模式呢,能不能举个例子?

答:

小偷(被观察者)把手伸进路人的钱包后(事件),给警察(观察者)发了条短信,曰:快来抓我哟!警察收到信息后,立马采取行动,把小偷按倒在地(行动)

这个小偷是不是很贱,偷东西还要告诉警察

2. 一个语文作业题:分析下面这句话的主、谓、宾 observable.subscribe(observer)

答:

- 主语:observable 被观察者

- 谓语:subscribe 订阅

- 宾语:observer 观察者

题外话:观察者.订阅(被观察者)貌似要更合理些,但对流式 API 的设计就造成影响了,比较起来明显是得不偿失的。

3. 主谓宾找的不错,能不能具体说说主语、谓语、宾语的具体含义

答:

主语:Observable 即被观察者(小偷)

它决定什么时候触发事件(行窃时间)以及触发怎样的事件(是行窃,还是助人为乐)

RxJava 使用 create() 方法来创建一个 Observable ,并为它定义事件触发规则:

   Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            subscriber.onNext("偷穿红上衣的女子");
            subscriber.onNext("偷穿白裤子的男孩");
            subscriber.onNext("偷戴帽子的老头");
            subscriber.onCompleted();//偷完收工
        }
    });

在这里,你创建了observable 之后,其参数OnSubscribe的call方法,并不会马上执行,只有当发生了订阅时(即observable.subscribe(observer))时,才会执行call方法。

你可以理解成这个小偷的确是太贱了,当没有警察盯着他时,他是不会作案的,只有他被警察盯着的时候,他才会作案。

宾语:Observer 即观察者 (警察)

它决定事件触发的时候将有怎样的行为(小偷伸手行窃,并给警察发短信后,警察要采取的动作)

RxJava 中的 Observer 接口的实现方式:

   Observer<String> observer = new Observer<String>() {
        @Override
        public void onNext(String s) {
            //这里的s就上面onNext方法里发送的信息“偷穿红上衣的女子”、"偷穿白裤子的男孩"、"偷戴帽子的老头",会连着输出三次。
            Log.d(tag, "小偷传递来的数据: " + s);
            //"警察采将其按倒在地"也会输出三次
            Log.d(tag, "警察采将其按倒在地");
            //也就是说:小偷每次行窃,警察都会采取行动
        }

        @Override
        public void onCompleted() {
            Log.d(tag, "抓完收工!");
        }

        @Override
        public void onError(Throwable e) {
            Log.d(tag, "oh,no让他给跑了");
        }
    };
  • onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为标志。
  • onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
  • 在一个正确运行的事件序列中, onCompleted() 和 onError() 有且只有一个,并且是事件序列中的最后一个。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。

除了 Observer 接口之外,RxJava 还内置了一个实现了 Observer 的抽象类:Subscriber。 Subscriber 对 Observer 接口进行了一些扩展,但他们的基本使用方式是完全一样的:

    Subscriber<String> subscriber = new Subscriber<String>() {
        @Override
        public void onNext(String s) {
            //这里的s就上面onNext方法里发送的信息“偷穿红上衣的女子”、"偷穿白裤子的男孩"、"偷戴帽子的老头",会连着输出三次。
            Log.d(tag, "小偷传递来的数据: " + s);
            //"警察采将其按倒在地"也会输出三次
            Log.d(tag, "警察采将其按倒在地");
            //也就是说:小偷每次行窃,警察都会采取行动
        }

        @Override
        public void onCompleted() {
              Log.d(tag, "抓完收工!");
        }

        @Override
        public void onError(Throwable e) {
           Log.d(tag, "oh,no让他给跑了");
        }
    };

不仅基本使用方式一样,实质上,在 RxJava 的 subscribe 过程中,Observer 也总是会先被转换成一个 Subscriber 再使用。所以如果你只想使用基本功能,选择 Observer 和 Subscriber 是完全一样的。当然他们也是有区别的,这里就不说了。

跟上文的被观察者类似,这里创建的Observer 或者Subscriber,是不会立即执行其回调方法的,只有当发生了订阅时(即observable.subscribe(observer)或者Observable.subscribe(Subscriber))时,Observer 或者Subscriber的回调方法才会执行

谓语 subscribe()方法 即订阅

创建了 Observable 和 Observer 之后,再用 subscribe() 方法将它们联结起来,整条链子就可以工作了。代码形式很简单:

    observable.subscribe(observer);
    // 或者:
    observable.subscribe(subscriber);

Observable.subscribe(Subscriber) 的内部实现是这样的(仅核心代码):

    // 注意:这不是 subscribe() 的源码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的核心代码。
    // 如果需要看源码,可以去 RxJava 的 GitHub 仓库下载。
    public Subscription subscribe(Subscriber subscriber) {
        subscriber.onStart();
        onSubscribe.call(subscriber);
        return subscriber;
    }

可以看到,subscriber() 做了3件事:

  1. 调用 Subscriber.onStart() 。这是一个可选的准备方法。
  2. 调用 Observable 中的 OnSubscribe.call(Subscriber) 。在这里,事件发送的逻辑开始运行。从这也可以看出,在 RxJava 中, Observable 并不是在创建的时候就立即开始发送事件,而是在它被订阅的时候,即当 subscribe() 方法执行的时候
  3. 将传入的 Subscriber 作为 Subscription 返回。这是为了方便 unsubscribe().

4. OK,主谓宾解释的还不错,帮我总结一下如何使用最基本的RxJava吧

答:

  1. 创建Observable
  2. 创建Observer或者Subscriber
  3. 订阅:observable.subscribe(observer); 或者 observable.subscribe(subscriber);

5.总结起来虽然就三步,但是具体代码还是很罗嗦,特别是回调方法很多,例如:创建观察者Observer或者Subscriber 时,我只关心onNext()方法,并不关心onComplete()方法和onError()方法, 能不能简化点呢

答:

当然可以

除了 subscribe(Observer) 和 subscribe(Subscriber) ,subscribe() 还支持不完整定义的回调,RxJava 会自动根据定义创建出 Subscriber 。形式如下:

    Action1<String> onNextAction = new Action1<String>() {
        // onNext()
        @Override
        public void call(String s) {
            Log.d(tag, s);
        }
    };
    Action1<Throwable> onErrorAction = new Action1<Throwable>() {
        // onError()
        @Override
        public void call(Throwable throwable) {
            // Error handling
        }
    };
    Action0 onCompletedAction = new Action0() {
        // onCompleted()
        @Override
        public void call() {
            Log.d(tag, "completed");
        }
    };

    // 自动创建 Subscriber ,并使用 onNextAction 来定义 onNext()
    observable.subscribe(onNextAction);
    // 自动创建 Subscriber ,并使用 onNextAction 和 onErrorAction 来定义 onNext() 和 onError()
    observable.subscribe(onNextAction, onErrorAction);
    // 自动创建 Subscriber ,并使用 onNextAction、 onErrorAction 和 onCompletedAction 来定义 onNext()、 onError() 和 onCompleted()
    observable.subscribe(onNextAction, onErrorAction, onCompletedAction);

注意到onNextAction 和onErrorAction的类型是Action1,而onCompletedAction 的类型是Action0 ,有何不同?

目前只要知道:

- Action1的回调方法call需要接收参数

- Action0的回调方法call不需要接收参数就可以了

6.上面只是简化了建观察者Observer或者Subscriber 的回调方法,对于被观察者Observable,有什么简化的方法吗

答:

当然有了

Observable.create() 方法是 RxJava 最基本的创造事件序列的方法。基于这个方法, RxJava 还提供了一些方法用来快捷创建事件队列,例如:

  • just(T…): 将传入的参数依次发送出来。
        Observable observable = Observable.just("Hello", "Hi", "Aloha");
        // 将会依次调用:
        // onNext("Hello");
        // onNext("Hi");
        // onNext("Aloha");
        // onCompleted();
  • from(T[]) : 将传入的数组或 Iterable 拆分成具体对象后,依次发送出来。
String[] words = {"Hello", "Hi", "Aloha"};
            Observable observable = Observable.from(words);
            // 将会依次调用:
            // onNext("Hello");
            // onNext("Hi");
            // onNext("Aloha");
            // onCompleted();

上面 just(T…) 的例子和 from(T[]) 的例子,都和之前的 create(OnSubscribe) 的例子是等价的。

7.那你把最初写的警察抓小偷的例子,用简便方法写一遍

  1. 第一种简便方法—>just
Observable.just("我在偷第一个人","我在偷第二个人","我在偷第三个人").subscribe(new Action1<String>() {
     @Override
     public void call(String s) {
         Log.e("小偷发出的消息",s);
         Log.e("警察","警察采取了行动");
     }
 });
  1. 第二种简便方法—>from
String [] msg={"我在偷第一个人","我在偷第二个人","我在偷第三个人"};
Observable.from(msg).subscribe(new Action1<String>() {
    @Override
    public void call(String s) {
        Log.e("小偷发出的消息",s);
        Log.e("警察","警察采取了行动");
    }
});
下面是log打印
07-17 20:11:35.536 15452-15452/pic.com.rxjavademo E/小偷发出的消息: 我在偷第一个人
07-17 20:11:35.536 15452-15452/pic.com.rxjavademo E/警察: 警察采取了行动
07-17 20:11:35.536 15452-15452/pic.com.rxjavademo E/小偷发出的消息: 我在偷第二个人
07-17 20:11:35.536 15452-15452/pic.com.rxjavademo E/警察: 警察采取了行动
07-17 20:11:35.536 15452-15452/pic.com.rxjavademo E/小偷发出的消息: 我在偷第三个人

怎么样?代码是不是简单多了

未完待续

时间: 2024-08-29 10:33:06

RxJava入门七问(一)的相关文章

Python爬虫入门七之正则表达式

在前面我们已经搞定了怎样获取页面的内容,不过还差一步,这么多杂乱的代码夹杂文字我们怎样把它提取出来整理呢?下面就开始介绍一个十分强大的工具,正则表达式! 1.了解正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑. 正则表达式是用来匹配字符串非常强大的工具,在其他编程语言中同样有正则表达式的概念,Python同样不例外,利用了正则表达式,我

转 Python爬虫入门七之正则表达式

静觅 » Python爬虫入门七之正则表达式 1.了解正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑. 正则表达式是用来匹配字符串非常强大的工具,在其他编程语言中同样有正则表达式的概念,Python同样不例外,利用了正则表达式,我们想要从返回的页面内容提取出我们想要的内容就易如反掌了. 正则表达式的大致匹配过程是:1.依次拿出表达式和文本中的字符比较,2.如果每一个

[WebGL入门]七,context的初始化

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 非常重要的初始化 从这次开始,开始着手WebGL的处理.首先是WebGL的初始化,完成渲染前的所有准备.前面的文章也给过HTML的雏形,还记得吧,像下面的代码这样. <html> <head> <title>WebGL TEST</title> <s

RxJava入门优秀博客推荐

RxJava用了快半年了,现在越来越离不开这个库,从使用到逐渐接触它的背后实现,突然想写点什么关于RxJava的内容.在酝酿如何组织内容的时候,就去看看自己关于RxJava的收藏,发现满满的干货! 1.抛物线:给 Android 开发者的 RxJava 详解,我的RxJava入门老师,从原理到用法到实现,面面俱到,非常nice! 2.hi大头鬼hi:深入浅出RxJava(一:基础篇),这是篇翻译文章,偏重用使用RxJava,对于操作符的讲解还不错,值得一看. 3.RxJava wiki:http

Rxjava入门与使用

认识 rxjava RxJava是 ReactiveX 在JVM上的一个实现,ReactiveX使用Observable序列 组合异步和基于事件 的程序. Observable(观察者) 和 Subscriber(订阅者)是两个主要的类.在 RxJava 上,一个 Observable 是一个发出数据流或者事件的类,Subscriber 是一个对这些发出的 items (数据流或者事件)进行处理(采取行动)的类.一个 Observable 的标准流发出一个或多个 item,然后成功完成或者出错.

RxJava入门系列四,Android中的响应式编程

RxJava入门系列四,Android中的响应式编程 在入门系列1,2,3中,我基本介绍了RxJava是如何使用的.但是作为一名Android开发人员,你怎么让RxJava能为你所用呢?这篇博客我将针对Android开发来介绍一下RxJava的使用场景. RxAndroid RxAndroid是为Android打造的RxJava扩展.通过RxAndroid可以让你的Android开发变得更轻松. 首先,RxAndroid中提供了AndroidSchedulers,你可以用它来切换Android线

RxJava入门系列三,响应式编程

RxJava入门系列三,响应式编程 在RxJava入门系列一,我向你介绍了RxJava的基础架构.RxJava入门系列二,我向你展示了RxJava提供的多种牛逼操作符.但是你可能仍然没能劝服自己使用RxJava,这一篇博客里我将向你展示RxJava提供的其他优势,没准了解了这些优势,你就真的想去使用RxJava了. 异常处理 直到目前为止,我都没有去介绍onComplete()和onError()方法.这两个方法是用来停止Observable继续发出事件并告知观察者为什么停止(是正常的停止还是因

七问C#关键字const和readonly

const和readonly经常被用来修饰类的字段,两者有何异同呢? const 1.声明const类型变量一定要赋初值吗? --一定要赋初值 public class Student { public const int age; } 生成的时候,会报如下错: 正确的应该这样写: public class Student { public const int age = 18; } 2.声明const类型变量可以用static修饰吗? --不可以 public class Student {

AppleWatch开发入门七——watchOS中通知的应用

AppleWatch开发入门七--watchOS中通知的应用 一.引言 在iOS系统中,支持的通知有两种类型:本地通知和远程通知.本地通知多用于计时类通知,远程的又称推送,多用于一些提示动态的提示信息.这里有相关通知的一些知识总结: 本地推送:http://my.oschina.net/u/2340880/blog/405491. 远程推送:http://my.oschina.net/u/2340880/blog/413584. 在watch中,通知是和iphone同步的,在iphone上的Ap