Android使用RxJava浅析

首先说一下自己为什么使用到了RxJava,因为在处理网络异步数据的时候,我一般是使用Thread+Handler或者AsyncTask来实现,直到接触了RxJava后,竟然可以如此便利的进行网络请求以及数据处理..然后就一发不可收拾,写篇博文记录一下

一,简介

RxJava是一种响应式编程(个人理解),他有两个重要元素Observable(被观察者,事件源)和Subscriber(观察者)。Observable发出一个事件,Subscriber处理这个事件。

例:用RxJava打印出”hello rxjava!”

1.我们可以通过Observable的create方法来创建一个Observable对象。

Observable mObservable = Observable.create(new Observable.OnSubscribe() {
        @Override
        public void call(Subscribersuper String> subscriber) {
            subscriber.onNext("hello rxjava!");
        }
});

注意create的参数,是一个OnSubscribe的实现类对象,OnSubscribe是Observable类中的内部接口。call方法中发出了一个“hello rxjava!”字符串。

2.创建一个Subscriber的实现类对象

Subscriber mSubscriber = new Subscriber() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String s) {
                System.out.println(s);
            }
};

实现onCompleted、onError、onNext三个方法,分别代表流程结束,出错,和数据处理。

3.通过subscribe方法完成事件源与观察者之间的订阅

mObservable.subscribe(mSubscriber);

完成订阅后,即会调用mSubscriber的onNext方法,打印出hello rxjava!

代码可进一步简化为:

        Observable
                .create(new Observable.OnSubscribe() {
                    @Override
                    public void call(Subscriber subscriber) {
                        subscriber.onNext("hello rxjava!");
                    }
                })
                .subscribe(new Action1() {
                    @Override
                    public void call(String string) {
                        System.out.println(string);
                    }
                });

subscribe参数除了Subscriber之外,还可以如下:

mObserable.subscribe(Action1, Action1, Action1);

参数中的三个Action1分别代表subscriber的onComplete,onError,onNext,此处我们只用到了onNext,因此代码可以简化为:

        Observable
                .create(new Observable.OnSubscribe() {
                    @Override
                    public void call(Subscriber subscriber) {
                        subscriber.onNext("hello rxjava!");
                    }
                })
                .subscribe(new Action1() {
                    @Override
                    public void call(String string) {
                        System.out.println(string);
                    }
                });

二.操作符

丰富的操作符是RxJava很正的强大之处,其可以对整个流程进行很好的控制。下面列出一些常用的操作符

1. just

其实上面的代码还可以继续简化:我们不仅可以通过create来创建一个Observable对象,还能通过just来创建。
如:

        Observable
                .just("hello rxjava!")
                .subscribe(new Action1() {
                    @Override
                    public void call(String string) {
                        System.out.println(string);
                    }
                });

just方法通过传入的value来返回一个相应的Observable对象

2.from

from接收一个集合参数,并将集合中的元素依次发出

        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        list.add("f");
        list.add("g");

        Observable
                .from(list)
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String string) {
                        System.out.println(string);
                    }
                });

程序会将list中的元素一个一个的发送给subscriber,subscriber负责将他们打印出来。
from与just的区别:同样传入一个集合list,对于just,subscriber收到的也会是一个list;而对于from,subscriber收到的是list中的item

3. map

上面的例子,提供的原始数据是hello rxjava!,那么如何在subscriber中打印出hello rxjava!_eric。最先想到的方法:

        Observable
                .just("hello rxjava!")
                .subscribe(new Action1() {
                    @Override
                    public void call(String string) {
                        System.out.println(string + "_eric");
                    }
                });

当然这样是可行的,但是subscriber作为观察者,他的作用是对接收到的数据做最直接的处理,不希望对数据进行转换。此时map出现了,map的作用是对observable发出的数据进行转换,将转换后的数据重新发出,转换后的数据可以与原始数据一致,当然也可以不一致!

        Observable
                .just("hello rxjava!")
                .map(new Func1<String, String>() {
                    @Override
                    public String call(String s) {
                        return s + "_eric";
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String string) {
                        System.out.println(string);
                    }
                });

这里map中对原始数据进行了处理。我们也可以增加多个map对数据进行一连串的变换。

        Observable
                .just("hello rxjava!")
                .map(new Func1<String, String>() {
                    @Override
                    public String call(String s) {
                        return s + "_eric";
                    }
                })
                .map(new Func1<String, Integer>() {
                    @Override
                    public Integer call(String s) {
                        return s.hashCode();
                    }
                })
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer hashCode) {
                        System.out.println(hashCode);
                    }
                });

此代码将hello rxjava! >hello rxjava!_eric>hashCode值,Subscriber中接收到hashCode并打印出来。

4. flatMap

接收一个observable的数据输出作为输入,转换为一个observable向下传递。

与map的区别:
1.map将接收到的数据处理后,转换为另一个数据传递下去
flatMap将接收到的消息转换为一个observable传递下去
2.如果map将消息处理为observable类型,那么subscriber中的call方法的输入也将是observable类型
而flatMap传递下去后,subscriber中输入的是observable所包含的类型T,而不是observable类型

也就是说,flatMap是将事件转化后返回一个Observable对象,但是这个对象并不是直接发送到Subscriber的回调方法中。他的原理是这样的:1.将数据转化为Observable对象。2.并不发送这个Obserable,而是将他激活,于是他开始发送事件。3.所有转为为的Observable发送的事件,全部交给同一个Observable,这个Observable负责将这些事件统一交给subscriber的回调方法。

        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add(null);
        list.add("c");
        list.add("d");
        list.add("e");
        list.add("f");
        list.add("g");

        Observable
                .just(list)
                .flatMap(new Func1<ArrayList<String>, Observable<String>>() {
                    @Override
                    public Observable<String> call(ArrayList<String> strings) {
                        return Observable.from(strings);
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        System.out.println(s);
                    }
                });
5.filter

过滤掉不符合条件的消息

6.take

指定消息数量

7.doOnNext

允许在处理观察者接收到消息前做一些事情, 比如将数据保存数据库等

        Observable
                .just(list)
                .flatMap(new Func1<ArrayList<String>, Observable<String>>() {
                    @Override
                    public Observable<String> call(ArrayList<String> list) {
                        return Observable.from(list);
                    }
                })
                .filter(new Func1<String, Boolean>() {
                    @Override
                    public Boolean call(String s) {
                        return s != null;
                    }
                })
                .take(3) // 最多返回3个结果,应注意此处与filter的先后关系:如果filter放在take前面,则是成功filter过后的3个;
                // 如果filter放在take后面,则是先取出3个再判断满不满足条件,如果不满足条件也不再增加
                .doOnNext(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        System.out.println("you can do something else about " + s);
                    }
                })
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String o) {
                        System.out.println(o);
                    }
                });

要注意filter和take的位置不同造成的不同结果。如上面代码:
如果filter放在take前面,则是成功filter过后的3个;
如果filter放在take后面,则是先取出3个再判断满不满足条件,如果不满足条件也不再增加

6. throttleFirst

允许在一个事件触发后的一段时间内丢弃新的事件。常用作去抖动过滤。例如
throttleFirst(500, TimeUnit.MILLISECONDS)表示丢弃掉事件处理后500ms内的事件

三、onComplete onError

一般情况下我们在回调中处理异常,这不仅要求每个回调都必须知道异常如何处理,导致重复代码,而且增加了代码之间的耦合性。
RxJava在整个消息传递的过程中,任意一个环节出现错误,就会跳过当前和后续的操作符,直接调用观察者的onError方法,操作符中不需要对错误进行处理;流程处理结束后会调用onComplete方法。因此,onComplete和onError是一定会被调用其一的。这大大简化了异常处理的方式。

四、调度器

现在的Android程序基本都离不开网络访问,另外开线程又是一件比较麻烦的事。
RxJava可以通过调度器来指定当前observable运行在哪个线程。

        Observable
                .just("www.baidu.com")
                .map(new Func1<String, String>() {
                    @Override
                    public String call(String s) {
                        return getHttpResponse(s);
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        textview.setText(s);
                    }
                });

使用observeOn()和subscribeOn()来指定线程。
subscribeOn:事件产生的线程
observeOn:事件消费的线程
上面代码可以看到,网络请求时是放在Schedulers.io()线程中,更新UI是放在main线程。RxJava定义了几种线程分类:

  • Schedulers.immediate(): 直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler。
  • Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。
  • Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。
  • Schedulers.computation(): 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。
  • 另外, Android 还有一个专用的 AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行。

这种在 subscribe() 之前写上两句 subscribeOn(Scheduler.io()) 和 observeOn(AndroidSchedulers.mainThread()) 的使用方式非常常见,它适用于多数的 『后台线程取数据,主线程显示』的程序策略。

浅析:(摘自http://gank.io/post/560e15be2dca930e00da1083)
subscribeOn和observeOn都进行了线程切换,不同的是,subscribeOn切换是在onSubscribe中,即在通知上一级OnSuscribe时,这时事件还没有发出,因此subscribeOn可以从事件发出的开端就造成影响。observeOn发生在他内建的subscriber中,即发生在给下一级subscriber发送事件时,因此observeOn控制的是他后面的线程。

subscribeOn和observeOn的混合调度:(详细解读可查看http://gank.io/post/560e15be2dca930e00da1083)

  • subscribeOn从事件创建时开始影响包括后面的线程。
  • observeOn影响的是他后面的线程。
  • 当流程中存在多个subscribeOn切换线程,只有第一个生效。

当然还有很多别的用法,大家慢慢去理解体会

你可能感兴趣的:(Android,android,rxjava)