RxJava 系列一 基础

作者: 人失格 | 来源:发表于2017-03-24 00:30 被阅读135次

    ​ 大概一年前就炒很火的Rxjava,本人也蹭热点上去学了两个月。学习坡度很高,整个过程也不是那么的顺利,再加上项目组很少有人用这个东西,所以把RxJava就搁置了。如果你问我RxJava好不好,答案一定是很好,但是它不是那么好上手,RxJava作用正如它的特点1, 异步 2. 基于观察者模式的函数式链式编程。如果能对设计模式有一定认识就已经很厉害了,大多数接触一两年Java这两部分都不会接触的很深。最近换了一家新公司,所以项目目前不是很忙的情况下,还要整改之前的老项目,在写代码的时候突然想到了之前的Rxjava。经过两年多的积累,感觉是时候引入Rxjava技术,Rxjava无意是最好的工具,很多的框架都使用它。

    核心概念

    ​ Rxjava中最重要的两个概念便是Observables和Subscribers,如果你对观察者模式很熟悉,那么你可以对应理解为被观察者和观察者。它们两者之间的关系为Observables发送数据,Subscribers对应着处理数据。

    ​ 问题在于数据在这两者之间是如何传递的,一个Observables可以发送任意的数据(包括空数据),然后它可以决定数据是否成功发送完成或者失败。对每一个Subscribers,一个Observable都会调用Subscriber.onNext()很多次,接下来伴随Subscriber.onComplete()或者Subscriber.onError()。

    ​ Observable一般不会立马发送数据直到有人订阅它们,在Rxjava中分为hot与cold Observable。两者的区别在于hot Observable会立刻发送数据,而cold Observable则会在subscriber注册时才会,如果是刚接触Rxjava暂时接触不到Hot Observable。文章下面的例子都是cold Observable。

    ​ 开始 我们先简单写一个完整的Observale

    Observable<String> observable = Observable.create(
        new Observable.OnSubscribe<String>(){
            public void call(Subscriber<? super String> sub){
                sub.onNext("Hello world");
                sub.onCompleted();
            }
        }
    )
    

    ​ 在我刚开始学习的时候,眼高手低觉得这么简单的东西,所以懒得看,可是人浮躁的话,到后来发现很多时候连基本的概念都没有搞清楚,走了很多的弯路。

    ​ 上面的代码,我们如果以后工程上肯定不会这儿写,但是这是RxJava最核心概念,因为它从代码基本解释了RxJava是如何运行的。一个Observable对象通过Observable.create静态方法创建的,在create方法的参数中我们传入了一个对象Observable.OnSubscribe,并复写了call方法,通过Subscriber对象 sub调用了onNext()和onCompleted()方法。可能很多新手看到这里早就晕了,我当时在学习的时候也是如此,不过不懂可以放着但是一定要把这段代码记住。

    ​ 上面这段代码只是简单做了一件事 便是输出『Hello world』 然后结束。接下来我们便创建一个Subscriber来消费这个数据:

    Subscriber<String> mySubscriber = new Subscriber<String>() {
        @Override
        public void onNext(String s) { System.out.println(s); }
    
        @Override
        public void onCompleted() { }
    
        @Override
        public void onError(Throwable e) { }
    };
    

    ​ 这段代码相对第一个段代码简单很多,无非创建了一个匿名对象 复写了Subscriber中的onNext方法并将字符串S打印出来。最后,我们已经有了一个Observable和一个SubScriber对象,现在我们要将两者连接起来使用subscribe():

    observable.subscribe(mySubscriber)
    

    ​ 当subscription建立起来,observable便会调用Subscriber的onNext方法 然后调用onComplete()方法,作为结果,mySubscriber输出『Hello World』。这便是Rxjava的最为核心的概念,如果你已经很熟悉了这个流程。恭喜你已基本掌握Rxjava。

    简练代码

    很多萌新看到这估计早炸锅了,就打印一句 helloworld 居然要写这么长的代码。其实上面只是完整展示Rxjava的工作流程,在工作中Rxjava提供了很多的简便方法来提供我们简化,看到后面你可能会被简练的代码所惊到。我们所是使用到的第一个方法便是Observable.just(),一行代码便完成第一段代码

    Observable<String> observable = Observable.just("Hello world");
    

    接下来我们简化Subscriber的方法,因为我们只关注onNext()方法,并不在乎

    onCompleted()或者onError(),所有我们使用Action1来简化Subscriber

    Action1<String> onNextAction = new Action1<String>() {
        @Override
        public void call(String s) {
            System.out.println(s);
        }
    };
    

    ​ Actions可以定义Subscriber中的三种方法 onNext() onError() onComplete(),所以我们之前的代码其实是这样的

    myObservable.subscribe(onNextAction,onErrorAction,onCompleteAction);
    

    最后我们得到的代码如下

    Observablel.just("Hello world").subscribe(new Action1<String>(){
      public void call(String s){
        System.out.println(a);
      }
    });
    

    最后我们可以使用JAVA 8 lambdas来摆脱这又臭又长的Actions代码。

    Observable.just("Hello world").subscribe(s ->System.out.println(s));
    

    目前在我写作的时候,Android才刚刚原生支持Java8,但是之前我们也可以使用JAVA 8 lambdas,主要是使用retrolambda这个插件来实现的。

    转化数据

    Rxjava让人又爱又恨的便是它那支持函数式链式编程,如果你不太了解函数式编程,可以提前搜索一下。如果现在我们想要在Hello world中加上我的名字怎么办呢

    Observable.just("Hello world! finch").subscribe(s -> System.out.println(s));
    

    但是我们在Rxjava却不会这么使用 因为一般来讲我们没法确认Observable数据来源,所以我们想到的是便是在subscribe中修改发送过来的数据

    Observable.just("Hello world!").subscribe(s -> System.out.println(s + "finch"));
    

    但是这么使用仍然不是Rxjava的最佳姿势,理由如下: 1. 我们在subscribe中通常是在Android的主线程操作,所以我们要做的操作要尽可能的轻 2. 从Rxjava的设计概念来讲,Subscribers的作为更多体现在对数据做出响应中,而不是对数据做出修改的操作。 最佳的使用姿势便是在Observable和Subscriber中插入中间件

    介绍操作符

    对于操作符,所有学习编程语言的人再熟悉不过了,在RxJava中也存在操作符,操作符用在 源Observable 和最后Subscriber之间来操作发射中的数据。Rxjava中有海量的操作符,但是我们刚学习时最好专注一少部分。

    为了解决上面的问题,我们引进第一个操作符map,map的作用在与将发射的数据转换为另外一个数据:

    Observable.just("Hello, world!")
        .map(new Func1<String, String>() {
            @Override
            public String call(String s) {
                return s + " -Dan";
            }
        })
        .subscribe(s -> System.out.println(s));
    

    再一次我们使用lambda来简化代码

    Observable.just("Hello world").map(s -> s + "finch").subscribe(s -> System.out.println(s));
    

    是不是很简练,厉害的来了,我们可以在Observable和Subscriber中插入无数map操作符来将数据随心所欲的处理。

    更多关于map()

    在实际编程中Map可以说是相当的好用,但是map很有意思的一点在于,它可以从源数据Observable转换不同类型的数据。

    Observable.just("Hello world")
      .map(new Func1<String,Integer>(){
        public Integer call(String s){
            return s.hashCode();
      }
    }).subscribe(i ->System.out.println(integer.toString()));
    

    是不是感觉很神奇 我们的数据源是一个字符串然后我将它转换为整数。

    按照惯例我们将代码使用Lambda来简化

    Observable.just("Hello world")
      .map(s ->s.hashCode())
      .subscribe(i -> System.out.println(Integer.toString()));
    

    然而起始我们可以将其中再加入好几个Map操作来完成我们需要的操作

    Observable.just("Hello world")
    .map(s -> s + "-Dan")
    .map(s ->s.hashCode())
    .map(i _>Integer.toString(i))
    .subscriber(s -> System.out.println(s));
    

    到了这也许你可能对Rxjava已经有了一定的了解了,说不定你可能已经嘀咕了 你这操作可能也没什么了不起。不过看到这里想必你也能理解两点

    1. Observable和Subscriber可以做任何事

      因为Rxjava不像网络请求框架okhttp或者glide之类拿到就可以用,它更像一个灵活锋利的瑞士军刀,使用需要你发挥想象力,但是在下一章讲到Android异步编程中的线程调度功能,可能你就感觉离不开它了,因为实在是太好用了。

    2. Observable和Subscriber在 数据的转换过程中是相对独立

      我们可以在源Observable和Subscriber中可以穿插无数map操作符,所以这整个过程是高度的灵活,在一个合适方法链中,我们可以很好的操作输入输出的数据

    光靠这两点,我们就可以看到这套系统的威力,实际上已经有很多的项目开源拿Rxjava来写 比如RxBus,在下一章我们将跳进更多的操作符池中,来更好的学习Rxjava

    相关文章

      网友评论

        本文标题:RxJava 系列一 基础

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