RxJava入门与提高(1)

前言

本教程是我自己学习Rxjava的系列总结。帮你从浅入深的学习RxJava。该系列借鉴了很多网上的优秀文章,并根据我的理解和学习经验,加以总结和抽取,方便大家理解。

据说RxJava的入门门槛高,而经过我这几天的学习,我反而不那么认为,精通我不敢说,但入门确实也不难,不信?我先来个简单的例子预热一下。

先创建个数据发射源,很好理解,就是发射数据用的:

Observablesender = Observable.create(new Observable.OnSubscribe() {
      @Override
      public void call(Subscribersubscriber) {
        subscriber.onNext("Hi,Weavey!");  //发送数据"Hi,Weavey!"
      }
});

再创建个数据接收源,同理,接收数据用的:

Observer receiver = new Observer() {

      @Override
      public void onCompleted() {
      //数据接收完成时调用
      }

      @Override  
      public void onError(Throwable e) {
      //发生错误调用
      }

      @Override
      public void onNext(String s) {
      //正常接收数据调用
            System.out.print(s);  //将接收到来自sender的问候"Hi,Weavey!"
      }
};

好了,将发射源和接收源关联起来:

sender.subscribe(receiver);

这样就形成RxJava一个简单的用法,sender发射"Hi,Weavey!",将会被receiver的onNext的接收,通过这个例子,也许你会想到“异步”、“观察者模式”,没错,这些都是RxJava所做的事情,并且让他们变得更简单和简洁,而RxJava所有的一切都将围绕这两个点展开,一个是发射数据,一个是接收数据,是不是很通俗易懂?如果你理解了这点或者你已经知道RxJava就是这么一回事,那么恭喜你,你已经一只脚跨进RxJava的大门了,如果不是!!!!那也无所谓,请继续往下看...

基本概念

论概念的重要性
在讲RxJava中各种强大的操作符之前,先说说最基本的东西——概念。举个不太恰当的例子,概念之于初学者,就像食物之于人,当你饿了,你会想吃面包、牛奶,那你为什么不去吃土呢,因为你知道面包牛奶是用来干嘛的,土是用来干嘛的。同理,前面已经说过,RxJava无非是发送数据与接收数据,那么什么是发射源,什么是接收源,这就是你应该明确的事,也是RxJava的入门条件之一,下面就依我个人理解,对发射源和接收源做个归类,以及RxJava中频繁出现的几个“单词”解释一通,说的不好还请海涵,欢迎补充。

Observable:发射源,英文释义“可观察的”,在观察者模式中称为“被观察者”或“可观察对象”;

Observer:接收源,英文释义“观察者”,没错!就是观察者模式中的“观察者”,可接收Observable、Subject发射的数据;

Subject:Subject是一个比较特殊的对象,既可充当发射源,也可充当接收源,为避免初学者被混淆,本章将不对Subject做过多的解释和使用,重点放在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;

基本用法

Observable的创建

1.使用create( ),最基本的创建方式:

normalObservable = Observable.create(new Observable.OnSubscribe() {
      @Override
      public void call(Subscriber subscriber) {
            subscriber.onNext("create1"); //发射一个"create1"的String
            subscriber.onNext("create2"); //发射一个"create2"的String
            subscriber.onCompleted();//发射完成,这种方法需要手动调用onCompleted,才会回调Observer的onCompleted方法
      }});

2.使用just( ),将为你创建一个Observable并自动为你调用onNext( )发射数据:

justObservable = Observable.just("just1","just2");//依次发送"just1"和"just2"

3.使用from( ),遍历集合,发送每个item:

List list = new ArrayList<>();

list.add("from1");

list.add("from2");

list.add("from3");

fromObservable = Observable.from(list);  //遍历list 每次发送一个

注意 just()方法也可以传list,但是发送的是整个list对象,而from()发送的是list的一个item

4.使用defer( ),有观察者订阅时才创建Observable,并且为每个观察者创建一个新的Observable:

deferObservable = Observable.defer(new Func0>() {
      @Override
      //注意此处的call方法没有Subscriber参数
      public Observable call() {
      return Observable.just("deferObservable");
}});

5.使用interval( ),创建一个按固定时间间隔发射整数序列的Observable,可用作定时器:

intervalObservable = Observable.interval(1, TimeUnit.SECONDS);//每隔一秒发送一次

6.使用range( ),创建一个发射特定整数序列的Observable,第一个参数为起始值,第二个为发送的个数,如果为0则不发送,负数则抛异常:

rangeObservable = Observable.range(10, 5);//将发送整数10,11,12,13,14

7.使用timer( ),创建一个Observable,它在一个给定的延迟后发射一个特殊的值,等同于Android中Handler的postDelay( )方法:

timeObservable = Observable.timer(3, TimeUnit.SECONDS);  //3秒后发射一个值

8.使用repeat( ),创建一个重复发射特定数据的Observable:

repeatObservable = Observable.just("repeatObservable").repeat(3);//重复发射3次

另外,还有

  • Observable.empty() 创建一个空的,不会发射任何事件(数据)的Observable
  • Observable.never() 创建一个不会发出任何事件也不会结束的Observable
  • Observable.error(new RuntimeException("fuck!")) 创建一个会发出一个error事件的Observable
    等等

Observer的创建

mObserver = new Observer() {

    @Override
    public void onCompleted() {
        LogUtil.log("onCompleted");
    }

    @Override
     public void onError(Throwable e) {

    }

    @Override
    public void onNext(String s) {
        LogUtil.log(s);
  }};

ok,有了Observable和Obsever,我们就可以随便玩了,任取一个已创建的Observable和Observer关联上,即形成一个RxJava的例子,如:

justObservable.subscribe(mObserver);

mObserver的onNext方法将会依次收到来自justObservable的数据"just1"、"just2",另外,如果你不在意数据是否接收完或者是否出现错误,即不需要Observer的onCompleted()和onError()方法,可使用Action1,subscribe()支持将Action1作为参数传入,RxJava将会调用它的call方法来接收数据,代码如下:

justObservable.subscribe(new Action1() {

      @Override
      public void call(String s) {
          LogUtil.log(s);
  }
});

以上就是RxJava最简单的用法。


Rxjava的优势---简洁(举例说明)

Rxjava的最大优势是代码简洁。这里的简洁不是说代码量少,是说,随着业务逻辑的增加,代码的可读性依然保持良好。没有之前的多层回调,一层一层的缩进的代码结构。具体就是,没增加一层回调或者功能,都可以用Rxjava的方法,连续点点点,增加功能。

看到这里,我也不知道我写的是否简单明了,也许你会想,“哎呀,写个异步的东西,怎么这么麻烦,为什么不用Thread+Handler呢”,那你就错了,RxJava也以代码的简洁深受广大用户喜爱,简洁不能理解为代码量少,而是随着逻辑的复杂,需求的更改,代码可依然能保持极强的阅读性,举个简单的例子(前方高能预警~~~),领导要我从数据库的用户表查找出所有用户数据,我二话不说拿出心仪的RxJava就写:

Observable.create(new Observable.OnSubscribe>() {

      @Override
      public void call(Subscriber> subscriber) {
          List userList = null;
          ···
          //从数据库获取用户表数据并赋给userList
          ···
          subscriber.onNext(userList);
        }
    }).subscribe(new Action1>() {

      @Override
      public void call(List users) {
      //获取到用户信息列表
    }

});

但是,领导突然又不想要所有用户了,只要名字叫“小明”的用户,行吧,领导最大,我改(假设名字唯一):

Observable.create(new Observable.OnSubscribe>() {

      @Override
      public void call(Subscriber> subscriber) {
          List userList = null;
          ···
          //从数据库获取用户表数据并赋给userList
          ···
          subscriber.onNext(userList);
      }

    }).flatMap(new Func1, Observable>() {

      @Override
      public Observable call(List users) {
          return Observable.from(users);
      }

    }).filter(new Func1() {

      @Override
      public Boolean call(User user) {
          return user.getName().equals("小明");
      }
    }).subscribe(new Action1() {

        @Override
        public void call(User user) {
          //拿到谜之小明的数据
    }
});

搞定,这时候领导又说,我不要小明了,我要小明的爸爸的数据,(坑爹啊~~),我继续改:

Observable.create(new Observable.OnSubscribe>() {

        @Override
        public void call(Subscriber> subscriber) {

            List userList = null;
            ···
            //从数据库获取用户表数据并赋给userList
            ···
            subscriber.onNext(userList);
        }

   }).flatMap(new Func1, Observable>() {

        @Override
        public Observable call(List users) {
              return Observable.from(users);
        }
        }).filter(new Func1() {

        @Override
        public Boolean call(User user) {
            return user.getName().equals("小明");
        }

     }).map(new Func1() {

        @Override
        public User call(User user) {
        //根据小明的数据user从数据库查找出小明的父亲user2
              return user2;
        }

     }).subscribe(new Action1() {

        @Override
        public void call(User user2) {
        //拿到谜之小明的爸爸的数据
        }
});

搞定,“还想怎么改?领导请说···”。

以上例子,涉及到几个操作符,初学者可能无法理解,但是无所谓,这不是重点,我的目的只是为了向你展示RxJava在需求不断变更、逻辑愈加复杂的情况下,依旧可以保持代码简洁、可阅读性强的一面,没有各种回调,也没有谜之缩进!

总结

看了以上所讲,如果你已经爱上了RxJava,如果你已经全部理解,我确信,你已经跨入RxJava的大门,剩下的只是时间的问题以及如何在实际开发场景中去应用的问题,那么下篇文章,我将继续讲解RxJava中各种强大的操作符,并尽量以实际开发过程中遇到的问题作为例子,提升自己的同时,帮助初学者迅速上手RxJava,如有写的不好的地方,还请见谅,真心欢迎各路大神指点,探讨相关技术。

欢迎继续收看:RxJava入门与提高-Subject篇(2)

作者:ZhangYushui

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

推荐阅读更多精彩内容