RxJava 使用详情

一概要:

RxJava已经被越来越多的人使用,提及。个人也觉得非常好用,优秀。这里做一个简单的归纳。

1,RxJava是什么:GitHub上介绍(翻译):一个在Java VM上使用可观测的序列来组成异步的,

基于事件的程序的库。简单点:一个实现异步操作的库。类似Handler,与AsyncTask。

2,RxJava优点是什么:相对于Handler/AsyncTask,RxJava使用非常简洁。使用一个链式引用就可以

将整个事件序列串联起来。

3,配置参考github:

https://github.com/ReactiveX/RxJava

https://github.com/ReactiveX/RxAndroid

二原理简析:

#RxJava的异步实现,是通过一个扩展的观察者模式来实现的。

#RxJava有四个基本概念:Observable(被观察者),Observer(观察者),subscribe(订阅),事件。

Observable与Observer通过subscribe来实现订阅关系,从而Observable可以在需要的时候发出事件通知Observer。

#与传统的观察者模式不同,RxJava的回调方法中除了onNext(类似onClick, onEvent),还定义了两个特殊的方法

onError, (事件队列异常),onComplete(事件队列结束语onError互斥)

三使用:

#基本使用

创建Observer(观察者),决定事件触发时的行为。(Subscriber是对Obsever封装了的观察者,比Observer多了

两个方法:onStart(在subscribe刚开始,事件还未被发送之前调用),onunsubscribe(取消订阅)。

        Observer<String> observer = new Observer<String>() {
            @Override
            public void onCompleted() {
                LogUtil.i(TAG, "onCompleted");
            }

            @Override
            public void onError(Throwable throwable) {
                LogUtil.i(TAG, "onError");
            }

            @Override
            public void onNext(String s) {
                LogUtil.i(TAG, "onNext:" + s);
            }
        };

创建Observable(被观察者),决定事件什么时候触发,以及触发怎么的事件。

        Observable observable = Observable.create(new Observable.OnSubscribe<String>() {

            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("1 times");
                subscriber.onNext("2 times");
                subscriber.onNext("3 times");
                subscriber.onCompleted();
            }
        });
#这里OnSubscribe作为create的参数,会被存储在observable对象中,相当于observable的计划表,当Observable

被订阅时,OnSubscribe的call方法就会被调用。然后就会触发订阅者(即观察者的)onNext(三次),onCompleted。

#create是创建事件序列的最基本方法。RxJava还提供其他创建事件序列的快捷方法,from、just...;

from方法:

        Observable observable = Observable.from(new String[]{"1 times", "2 times", "3 times"});
        //将会依次调用
        //onNext("1 times");
        //onNext("2 times");
        //onNext("3 times");
        //onCompleted();
j ust方法:
        Observable observable = Observable.just("1 times", "2 times", "3 times");
        //将会依次调用
        //onNext("1 times");
        //onNext("2 times");
        //onNext("3 times");
        //onCompleted();
Subscribe订阅,创建Observable与Observer之后,subscribe方法将两者联系起来。
        observable.subscribe(observer);
        //或
        observable.subscribe(subscriber);

subscribe的主要核心代码:

        // 注意:这不是 subscribe() 的源码,而是将源码中与性能、兼容性、扩展性有关的代码剔除后的核心代码。
        public Subscription subscribe(Subscriber subscriber) {
            subscriber.onStart();
            onSubscribe.call(subscriber);
            return subscriber;
        }
#重点onSubscribe.call(subscriber)方法,前面分析的create方法,方法中的参数OnSubscribe,作为ObServable的计划表。
除了subscribe(Observer)和subscribe(Subscriber)方法外,还支持不完整定义回调:
        Action1<String> nextAction = new Action1<String>() {
            @Override
            public void call(String s) {

            }
        };
        Action1<Throwable> errorAction = new Action1<Throwable>() {
            @Override
            public void call(Throwable o) {

            }
        };
        Action0 completeAction = new Action0() {
            @Override
            public void call() {

            }
        };
        //自动创建Subscriber,使用nextAction,来定义onNext
        observable.subscribe(nextAction);
        //自动创建Subscriber,使用nextAction,errorAction来定义onNext与onError
        observable.subscribe(nextAction, errorAction);
        //自动创建Subscriber,使用nextAction,errorAction,completeAction来定义onNext,onError,onComplete
        observable.subscribe(nextAction, errorAction, completeAction);

下面举两个例子:

1,将字符串数组names中的字符串依次打印出来

        //将数组names中的所有字符串打印出来。
        String[] names = new String[]{"wangwu", "zhangsan", "lisi"};
        Observable.from(names)
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        LogUtil.i(TAG, "name:" + s);
                    }
                });
2,由图片id,取得图片并显示:
        int resId = R.drawable.aa2;

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

            @Override
            public void call(Subscriber<? super Drawable> subscriber) {
                LogUtil.i(TAG, "currentThread:" + Thread.currentThread());
                Drawable drawable = MainActivity.this.getResources().getDrawable(R.drawable.aa2);
                subscriber.onNext(drawable);
                subscriber.onCompleted();
            }
        })
                .subscribe(new Subscriber<Drawable>() {

                    @Override
                    public void onStart() {
                        super.onStart();
                        LogUtil.i(TAG, "onStart");
                    }

                    @Override
                    public void onNext(Drawable drawable) {
                        LogUtil.i(TAG, "currentThread:" + Thread.currentThread());
                        LogUtil.i(TAG, "onNext");
                        iv_content.setImageDrawable(drawable);
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        LogUtil.i(TAG, "onError");
                    }

                    @Override
                    public void onCompleted() {
                        LogUtil.i(TAG, "onCompleted");
                    }
                });

高级使用:

1,变换:map、flatMap:将事件序列中的事件或整个事件序列,加工成不同的事件,或事件序列。

场景一,已知学生数组,打印学生的姓名:

        Student[] students = ...;
        Subscriber<String> subscriber = new Subscriber<String>() {
            @Override
            public void onNext(String name) {
                Log.d(tag, name);
            }
    ...
        };
        Observable.from(students)
                .map(new Func1<Student, String>() {
                    @Override
                    public String call(Student student) {
                        return student.getName();
                    }
                })
                .subscribe(subscriber);
场景二,已知学生数组,打印学生的所选课程(课程不唯一):
我们当然可以使用for循环:
        Student[] students = ...;
        Subscriber<Student> subscriber = new Subscriber<Student>() {
            @Override
            public void onNext(Student student) {
                List<Course> courses = student.getCourses();
                for (int i = 0; i < courses.size(); i++) {
                    Course course = courses.get(i);
                    Log.d(tag, course.getName());
                }
            }
    ...
        };
        Observable.from(students)
                .subscribe(subscriber);
或者flatMap:
        Student[] students = ...;
        Subscriber<Course> subscriber = new Subscriber<Course>() {
            @Override
            public void onNext(Course course) {
                Log.d(tag, course.getName());
            }
    ...
        };
        Observable.from(students)
                .flatMap(new Func1<Student, Observable<Course>>() {
                    @Override
                    public Observable<Course> call(Student student) {
                        return Observable.from(student.getCourses());
                    }
                })
                .subscribe(subscriber);
#flatMap与map不同,call方法返回的是Observable对象。

线程控制要求,利用subscribeOn与observeOn来实现线程控制。subscribeOn实现的是事件发送所在线程,observeOn

事件消耗所在线程(下一个操作),onserveOn可以调用多次,即事件消耗可以多次线程切换。

Scheduler实现异步操作:

        Observable.just(1, 2, 3, 4) // IO 线程,由 subscribeOn() 指定
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.newThread())
                .map(mapOperator) // 新线程,由 observeOn() 指定
                .observeOn(Schedulers.io())
                .map(mapOperator2) // IO 线程,由 observeOn() 指定
                .observeOn(AndroidSchedulers.mainThread)
                .subscribe(subscriber);  // Android 主线程,由 observeOn() 指定
延伸doOnSubscribe,与subscriber的onStart方法一样在subscribe之后,事件发送前被调用。但是不同点是doOnSubscribe可以

被指定线程。默认情况下doOnSubscribe与subscribe所在的线程相同,如果在doOnSubscribe后又subscribeOn()定义线程,则

依从doOnSubscribe之后的最近的subscribeOn所指定线程:

        Observable.create(onSubscribe)
                .subscribeOn(Schedulers.io())
                .doOnSubscribe(new Action0() {
                    @Override
                    public void call() {
                        progressBar.setVisibility(View.VISIBLE); // 需要在主线程执行
                    }
                })
                .subscribeOn(AndroidSchedulers.mainThread()) // 指定主线程
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);

四避免内存泄漏:

使用CompositeSubscription,收集每一次Subscription,然后在onDestroy中统一注销。

CompositeSubscription compositeSubscription = new CompositeSubscription();//第一步,初始化CompositeSubscrpiton

        compositeSubscription.add(    //第二步,add Subscription
                Observable.from(names)
                        .subscribe(new Action1<String>() {
                            @Override
                            public void call(String s) {
                                LogUtil.i(TAG, "name:" + s);
                            }
                        })
        );

    @Override
    protected void onDestroy() {
        super.onDestroy();//在Activity销毁的时候,统一取消订阅,释放资源
        if(compositeSubscription.isUnsubscribed()){
            compositeSubscription.unsubscribe();
        }
    }

文章参考:http://gank.io/post/560e15be2dca930e00da1083#toc_1


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值