RxJava 使用详情

来源:互联网 发布:淘宝的一件代发是怎么 编辑:程序博客网 时间:2024/06/05 17:16

一概要:

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();
just方法:
        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


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 有异物掉入眼睛怎么办 空调出风口掉入异物怎么办? 超星尔雅挂科了怎么办 泰拉瑞亚神庙祭坛挖掉了怎么办 泰拉瑞亚不小心把数据删除了怎么办 足球守门员遇到单刀球怎么办 猫见到主人就跑怎么办 手机玩游戏闪屏怎么办 满身起小疙瘩很痒怎么办 出门在外忘记带备用胸罩怎么办 去泰国浮潜近视怎么办 gta5线上马丁任务卡了怎么办 双肩背包黑色的皮子褪色怎么办 lspdfr在游戏里崩溃怎么办 gta5钱超过21亿怎么办 假警察要带走我怎么办 遇到假警察拦车怎么办 大连船员体检眼力不合格怎么办 禁行如果通过了怎么办 钻戒的戒圈磨损怎么办 多肉的肉掉了怎么办 电脑自带鼠标动不了怎么办 笔记本电脑自带鼠标动不了怎么办 包包弹簧扣松了怎么办 耳钉氧化成黑色怎么办 想买点小股票玩玩要怎么办 玩具子弹打到眼睛怎么办 玩具汽车遥控器码乱了怎么办 索尼A7屏幕花了怎么办? 汽车冷冻器坏了怎么办 sim卡损坏怎么办 补卡 异或门一个输入怎么办 迷你世界加不了好友怎么办 电脑软件显示无效应用程序怎么办 美的滚筒洗衣机打不开门怎么办 手机存储卡坏了怎么办 回南天地板潮湿怎么办 lg滚筒洗衣机门打不开怎么办 西门子滚桶洗衣机门打不开怎么办 洗衣机离合器螺丝卸不动怎么办 门锁保险栓坏了怎么办