美文网首页Android-RxJavaIT 其他文章Android知识
我所理解的RxJava——上手其实很简单(一)

我所理解的RxJava——上手其实很简单(一)

作者: Weavey | 来源:发表于2016-08-27 03:30 被阅读116156次

前言

相信各位看官对RxJava早有耳闻,那么关于什么是RxJava我就不再赘述了,不知道的可自行百度。如果你已经大致了解过什么是RxJava,想开始学习,那么本文不失为你良好的选择,为什么这么说呢,因为我也是刚学几天,正所谓“知己知彼,百战不殆”。网上流传,RxJava的入门门槛高,而经过我这几天的学习,我反而不那么认为,精通我不敢说,但入门确实也不难,不信?我先来个简单的例子预热一下。

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

   Observable<String> sender = Observable.create(new Observable.OnSubscribe<String>() {
         
           @Override
            public void call(Subscriber<? super String> subscriber) {

                subscriber.onNext("Hi,Weavey!");  //发送数据"Hi,Weavey!"
            }
        });

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

   Observer<String> receiver = new Observer<String>() {
           
            @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的入门条件之一,下面就依我个人理解,对发射源和接收源做个归类,以及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<String>() {
    @Override
    public void call(Subscriber<? super String> 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<String> 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<Observable<String>>() {
    @Override
    //注意此处的call方法没有Subscriber参数
    public Observable<String> 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次
  • Observer的创建
mObserver = new Observer<String>() {
    @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()方法,可使用Action1subscribe()支持将Action1作为参数传入,RxJava将会调用它的call方法来接收数据,代码如下:

justObservable.subscribe(new Action1<String>() {
      @Override
      public void call(String s) {

            LogUtil.log(s);
       }});

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

       Observable.create(new Observable.OnSubscribe<List<User>>() {
            @Override
            public void call(Subscriber<? super List<User>> subscriber) {
                List<User> userList = null;
                ···
                //从数据库获取用户表数据并赋给userList
                ···
                subscriber.onNext(userList);
            }
        }).subscribe(new Action1<List<User>>() {
            @Override
            public void call(List<User> users) {
                
                //获取到用户信息列表
            }
        });

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

      Observable.create(new Observable.OnSubscribe<List<User>>() {
            @Override
            public void call(Subscriber<? super List<User>> subscriber) {
                List<User> userList = null;
                ···
                //从数据库获取用户表数据并赋给userList
                ···
                subscriber.onNext(userList);
            }
        }).flatMap(new Func1<List<User>, Observable<User>>() {
            @Override
            public Observable<User> call(List<User> users) {
                return Observable.from(users);
            }
        }).filter(new Func1<User, Boolean>() {
            @Override
            public Boolean call(User user) {
                return user.getName().equals("小明");
            }
        }).subscribe(new Action1<User>() {
            @Override
            public void call(User user) {
                //拿到谜之小明的数据
            }
        });

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

  Observable.create(new Observable.OnSubscribe<List<User>>() {
            @Override
            public void call(Subscriber<? super List<User>> subscriber) {
                List<User> userList = null;
                ···
                //从数据库获取用户表数据并赋给userList
                ···
                subscriber.onNext(userList);
            } 
       }).flatMap(new Func1<List<User>, Observable<User>>() {
            @Override
            public Observable<User> call(List<User> users) {
                return Observable.from(users);
            }
        }).filter(new Func1<User, Boolean>() {
            @Override
            public Boolean call(User user) {
                return user.getName().equals("小明");
            }
        }).map(new Func1<User, User>() {
            @Override
            public User call(User user) { 
                //根据小明的数据user从数据库查找出小明的父亲user2
                return user2;
            }
        }).subscribe(new Action1<User>() {
            @Override
            public void call(User user2) {
              //拿到谜之小明的爸爸的数据
            }
        });

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


总结

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


本猿已转行,勿念。

相关文章

网友评论

  • foreverluckyman:楼主威武,一看就懂了
  • 9e7ec18f940e:不错,看来几篇都不懂,看来这篇恍然大悟
  • RoJacKing:谢谢,看别的文章一脸懵逼,概念还没理解看不懂,博主写的接地气,通俗易懂,感谢
  • WeroNG:哈哈哈,领导一脸懵逼👍
  • messiGao:对于不同线程的使用的确比较方便。我有个小问题,如果是一个类A做了发布动作,接收订阅的动作是在另外一个类B中去做,那么新建的这个Observable对象如何传递。
  • Chinesszz:能不能把RxJava的版本说明下,因为1和2的区别很大哎
  • 一休日记:讲句真心话,有些文章吧,看着作者很牛逼。但是你们要想啊,我一个初学者用都不会用,完全还体会不到rxjava的优势的时候,你跟我说那些原理有什么用呢?我根本还没提的起来兴趣,我怎么有勇气把所有的原理看完呢?
  • 般若同学:今年再看和去年看的时候,体会不一样了,楼主牛逼~
  • 4a68ecaec8d8:不错,基本理解
  • ac972c69554c:文章不错!
  • 18b4eaf9eced:《我所理解的RxJava——上手其实很简单(一) - 简书》写的不错不错,收藏了。

    推荐下,分布式作业中间件 Elastic-Job 源码解析 16 篇:http://tinyurl.com/y93r9wfg


    51abdc2d8943:不错不错
    8afe04d66ee7:写的不错,谢谢博主;已 收 藏~
  • 码锻:你那个模拟请求数据库时不应该设置为在子线程吗?接受数据在主线程
  • 一二三是五六十:世界需要你这样说人话的人
  • 张正yi:这样的好文章真的有很多,但这是我看到的关于Rxjava的第一篇
  • zhangwenhaojf40:写的真好,从源头说起!看了那么多都没看懂,唯独看了你的
  • d4afd12fe754:在发送端发送应该指明 在哪个线程Obscribeon();
  • d4afd12fe754:你上面感觉都没有指明线程 那它不会主线吗? 如果在主线程的话
  • 一点愁:两条sql语句就可以轻松解决的事情,在这里又是过滤又是来回转换的,不仅复杂度提高了,代码量也增加了,又是传值又是转换迷之混乱没觉得可读性在哪里,不用rxjava真正去自己写一个方法一条sql就可以轻松搞定的事情,在这里我却看到了迷之转换,ReactiveX的初衷是要这么用吗,若是真的那可用性值得怀疑
  • 8346bc44ec8f:就喜欢写的这样简单的。
  • 55a07bf6652a:真麻烦,不好用
  • 84ba53df2369:写得很棒!看了好多博客最后看了这个就搞明白了!
  • 780320635971:赞的不行!

    已出师
  • 风影_638f:有钱的赞赏下。写的很好
  • 戴定康:这一篇更容易理解 https://www.daidingkang.cc/2017/05/19/Rxjava/
    陈添:作为一个新手,表示看不懂
    80e1672bb160:这个更6
  • dc24fc83b9b6:写的很通俗易懂,参考扔物线大神的总纲(http://gank.io/post/560e15be2dca930e00da1083#toc_1),学习步骤很顺滑。
  • 我是黄教主啊:写的真好,请问我可以转载吗,我会注明出处的
  • 354c1c9731fb:写的好,初学者的福利,其实用过eventBus 再看Rxjava感觉异曲同工,
  • Oterman:不错,就准备看这个来入门了
  • b6502e5fd1b8:感谢楼主分享,想问下RxJava 在 b/s 应用上有什么应用场景?
  • 叮宕:我总觉得subscribe这个方法的名字起得不好,被观察者允许这个观察者观察订阅它。在uml中调用看成发送消息,被观察者给观察者发送允许订阅其自身的消息,方法的命名可以换成接受订阅,acceptSubscribe()
  • 戴定康:其实还可以用Lambda表达式,我推荐一篇文章给大家学习Lambda表达式的使用:http://daidingkang.cc/2017/05/11/java8-Lambda/
  • a7f899c4ef21:这是我看的所有关于RxJava讲解的博文中,最清新脱俗的了。好文!
  • 一休日记:挺好的,慢慢的看得进去了。一开始看《给 Android 开发者的 RxJava 详解》,可能水平不行,着实有点吃力。
  • 明明_白_白:写的非常好,跟之前看的RxJava文章都不一样,但更容易让人了解RxJava到底便捷在哪里。
  • Merbng:Rxjava2更新了好多不一样的东西。可以更新一下
  • W_BinaryTree:虽然貌似很久远了。不过最近很多人还在看。希望博主更新一下。 Rxjava1中 create()应该是最不该使用的方法之一,不支持backpressure,没有自动的error处理等等种种的缺陷。
  • 3Q竹林:good!
  • jayli2233:可以
  • 繁体字遇上简体字:很不错的技术文章,以前看没看懂这次准备入手
  • Dinos:入坑,关注微信。。=_=,期待作者持续更新。。。
  • 魏震洲:感谢大神分享:pray:
  • William_L:通俗易懂,不错!
  • 3927bf2911c4:楼主大神,顺便把retrofit、butterknife、dagger2都讲一下吧
  • yejg:厉害,终于对rxjava不会一脸懵逼了
  • 聪葱忙忘:看过写的最好的一篇文章
  • a16fed40d19a:看这篇文章总算是懂RXJAVA了
  • 0795bf4f06ba:不得不评论,写的不错,真心通俗易懂
  • 爱吃板栗的小女孩:开篇终于不是一堆概念字了:heart_eyes:
  • 0f2e0a1e8363:慢慢学习
  • LsFern:很不错,通俗易懂。期待更高深的文章
  • ListenerGao:不错,很容易理解。
  • 3c7f56742d79:博主,是不是就可以理解成观察者模式?
  • cuixbo:通俗易懂
  • aad3a0c8a574:突然想到一个问题,RxJava写程序的话时空复杂度怎么算的?
  • 任飞:希望作者写点关于rxjava+okhttp+retorfit
  • Wang_Guan:恩,确实比较简单易懂~感觉蛮好的。
  • f45b845bf06a:还行~不过这个有人比你更早出了吧?而且封装的还不错。
  • Tauruse:博主加油,期待后面的内容 :smile:
  • 1bd221f8bd5d:终于找到我能看懂的RxJava介绍了 :sob:
    写的太好了 简单易懂 :+1:
    Weavey: @1bd221f8bd5d 感谢支持😑😑
  • 16af3c477491:赞一个,好文
  • 捡淑:马克
    Mr_Rains:我擦 怎么哪里都看得到你啊
  • 虾米咬小米:看了很多RxJava的文章,然后刚看到你的文章,试验了一遍,Rxjava...的初步用法,终于理解了.
    博主,
    赶快出(二)
    Weavey:@飞飞happy 在起稿了,会尽快出,感谢支持~~~
  • 79964e1ba03f:哎啊,写的真不赖。
  • 健康早餐:受不了了,写的真好
  • Waizau:看到标题带(一),请问(二)去哪里了?去哪里了?去哪里了?== :smiley:
    Weavey:@Waizau 莫慌,会尽快出二,感谢支持 (^_^)
  • 极乐君:大神!坚持写啊!
    个人建站,做技术问答的,欢迎一起交流!——http://www.dreawer.com
    7a59f7216ff7:@Weavey 大神,写的真心好。通俗易懂
    Weavey:@极乐网络 互相学习!会坚持的!!
  • 奋斗的Leo:。。。我闲着没事做,将百分之70的操作符都写了demo
    Weavey:@奋斗的Leo :+1: :+1: 大神
  • 贰yang:写的很明白,例子很给力,赞!
  • 340a55154ed4:监督你写下一篇
  • Wower_Lau:通俗易懂,好好好!
  • 世锋日上:很好,很清晰,受教了!

本文标题:我所理解的RxJava——上手其实很简单(一)

本文链接:https://www.haomeiwen.com/subject/goansttx.html