RxJava

本文介绍了RxJava的基本概念和核心组件,通过实例演示了如何利用RxJava进行异步操作及事件处理,涵盖Observable、Observer等关键API,并解析了常用操作符如map、flatMap等的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RxJava入门学习

ReactiveX是Reactive Extensions的缩写,一般简写为Rx,(响应式)

extensions  英[ɪks'tenʃnz]
美[ɪks'tenʃnz]
n.  延伸; 扩展名; 延长( extension的名词复数 ); [逻辑学] 外延;

reactive    英[riˈæktɪv]
美[riˈæktɪv]
adj.    反应的; 活性的; 电抗的;

gitHub的地址:

https://github.com/ReactiveX/RxJava

https://github.com/ReactiveX/RxAndroid

首先在as中添加依赖:

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

compile 'io.reactivex.rxjava2:rxjava:2.0.1'

Rxjava是什么?

RxJava 在 GitHub 主页上的自我介绍是 “a library for composing asynchronous and event-based programs using observable sequences for the Java VM”(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。

异步操作的库

好处再哪里?

异步操作有AsyncTask和handler,但是RxJava更简洁

假设有这样一个需求:
界面上有一个自定义的视图 imageCollectorView ,它的作用是显示多张图片,并能使用 addImage(Bitmap) 方法来任意增加显示的图片。现在需要程序将一个给出的目录数组 File[] folders 中每个目录下的 png 图片都加载出来并显示在 imageCollectorView 中。需要注意的是,由于读取图片的这一过程较为耗时,需要放在后台执行,而图片的显示则必须在 UI 线程执行。常用的实现方式有多种,我这里贴出其中一种:

new Thread() {
    @Override
    public void run() {
        super.run();
        for (File folder : folders) {
            File[] files = folder.listFiles();
            for (File file : files) {
                if (file.getName().endsWith(".png")) {
                    final Bitmap bitmap = getBitmapFromFile(file);
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            imageCollectorView.addImage(bitmap);
                        }
                    });
                }
            }
        }
    }
}.start();

RaJava的做法:

Observable.from(folders)
.flatMap(new Func1<File, Observable<File>>() {
    @Override
    public Observable<File> call(File file) {
        return Observable.from(file.listFiles());
    }
})
.filter(new Func1<File, Boolean>() {
    @Override
    public Boolean call(File file) {
        return file.getName().endsWith(".png");
    }
})
.map(new Func1<File, Bitmap>() {
    @Override
    public Bitmap call(File file) {
        return getBitmapFromFile(file);
    }
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Bitmap>() {
    @Override
    public void call(Bitmap bitmap) {
        imageCollectorView.addImage(bitmap);
    }
});

代码虽然多了,但是逻辑更简洁。

API 介绍和原理简析

RaJava观察者模式扩展

RxJava使用的是观察者模式

Observable :被观察者(类似于Button、小偷)

Observer :观察者(类似于OnClickListener 、警察)、Subscriber(对Observer 接口进行了一些扩展)

注意:

在 RxJava 的 subscribe 过程中,Observer 也总是会先被转换成一个 Subscriber 再使用

subscribe :订阅(setOnClickListener())

事件:(onClick())

RxJava的回调事件:

  • onNext() (相当于 onClick() / onEvent())

  • onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为标志。

  • onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
    在一个正确运行的事件序列中, onCompleted() 和 onError() 有且只有一个,并且是事件序列中的最后一个。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。

基本的实现

Observable的创建

Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> e) throws Exception {
            Log.d("haha", "subscribe (observable thread) " + Thread.currentThread().getName());
            e.onNext(6);
        }
    });


Observable<Integer> just = Observable.just(3,4,5);

//Observable<Integer> from = Observable.fromArray(3,4,5);

    Observer<Integer> observer = new Observer<Integer>() {
        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onNext(Integer value) {
            Log.d("haha", "onNext (subscriber thread) " + Thread.currentThread().getName());
            Log.d("haha", "onNext integer:" + value);
        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
    };

    just.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(observer);

Consumer

observable.subscribeOn(Schedulers.io())//上游指定的线程(一般比较耗时的操作)
            .observeOn(AndroidSchedulers.mainThread())//下游指定的线程
            .subscribe(new Consumer<Drawable>() {
                @Override
                public void accept(Drawable drawable) throws Exception {
                    //处理 onNext()
                }
            }, new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    //处理 onError()
                }
            }, new Action() {
                @Override
                public void run() throws Exception {
                    //处理 onComplete()
                }
            });

Scheduler

        final int res = R.mipmap.ic_launcher;
        Observable<Drawable> observable = new Observable<Drawable>() {
            @Override
            protected void subscribeActual(Observer<? super Drawable> observer) {
//                使用drawable资源但不为其设置theme主题
//                Drawable drawable = ResourcesCompat.getDrawable(getResources(), res, null);

//                使用默认的activity主题
                Drawable drawable = ContextCompat.getDrawable(MainActivity.this, res);

//                使用自定义主题
//                ResourcesCompat.getDrawable(getResources(), res, anotherTheme);

//                过时的方法
//                Drawable drawable = getResources().getDrawable(res);
                observer.onNext(drawable);
                observer.onComplete();
            }
        };

        observable.subscribeOn(Schedulers.io())//上游指定的线程(一般比较耗时的操作)
                .observeOn(AndroidSchedulers.mainThread())//下游指定的线程
                .subscribe(new Consumer<Drawable>() {
                    @Override
                    public void accept(Drawable drawable) throws Exception {
                        mImageView.setImageDrawable(drawable);
                    }
                });

Observable:一般执行比较耗时的操作

Consumer(在Rxjava1.0里是observe):接受Observable onNext()中指定的参数

操作符

range

Observable.range(1,5)
            .subscribe(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) throws Exception {
                    Log.d("haha", "integer:" + integer);

                }
            });

timer

//延迟加载 可以替换 handler.postDelayed 
    Observable.timer(5, TimeUnit.SECONDS)
            .subscribe(new Consumer<Long>() {
                @Override
                public void accept(Long aLong) throws Exception {
                    Log.d("haha ", Thread.currentThread().getName());
                }
            });

interval

//3秒发送一次,后续每1秒发送一次

Observable.interval(3,1,TimeUnit.SECONDS)
            .subscribe(new Consumer<Long>() {
                @Override
                public void accept(Long aLong) throws Exception {
                    Log.d("haha", Thread.currentThread().getName());
                }
            });

repeat

Observable.just("hello", "world")
            .repeat(3)
            .subscribe(new DisposableObserver<String>() {
                @Override
                public void onNext(String value) {
                    Log.d("haha", value);

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onComplete() {
                    Log.d("haha", "onComplete");
                }
            });

defer

该操作符能保证订阅执行时数据源是最新的数据。

没用defer:

String src = "taoge";

private void deferDemo() {

    Observable<String> observable = Observable.just(src);

    DisposableObserver<String> disposableObserver = new DisposableObserver<String>() {
        @Override
        public void onNext(String value) {
            Log.d("haha", value);
        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
    };
    src = "taoge 222";
    observable.subscribe(disposableObserver);
}

使用defer:

String src = "taoge";

private void deferDemo() {

    Observable<String> observable = Observable.defer(new Callable<ObservableSource<? extends String>>() {
        @Override
        public ObservableSource<? extends String> call() throws Exception {
            return Observable.just(src);
        }
    });

    DisposableObserver<String> disposableObserver = new DisposableObserver<String>() {
        @Override
        public void onNext(String value) {
            Log.d("haha", value);
        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
    };
    src = "taoge 222";
    observable.subscribe(disposableObserver);
}

doOnXXX

使用这一组操作符,我们能在使用简单Consumer回调对onNext方法作处理时,依然能对其他三种回调做处理:

doOnSubscribe
在onNext之前做初始化操作。

doOnNext
允许我们在每次输出一个元素之前做一些额外的事情。

doOnError
当出现错误时复写方法做处理

doOnComplete
当onNext执行完时,做最后总处理

在doOnSubscribe()之后,使用subscribeOn()就可以指定其运行在哪中线程。

Observable.just("hello world")
            .doOnSubscribe(new Consumer<Disposable>() {
                @Override
                public void accept(Disposable disposable) throws Exception {
                    Log.d("haha", "doOnSubscribe: " + Thread.currentThread().getName());
                }
            })
            .subscribeOn(Schedulers.io())
            .doOnNext(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    Log.d("haha", "doOnNext: " + Thread.currentThread().getName());
                }
            })
            .doOnError(new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    Log.d("haha", "doOnError: " + Thread.currentThread().getName());
                }
            })
            .doOnComplete(new Action() {
                @Override
                public void run() throws Exception {
                    Log.d("haha", "doOnComplete: " + Thread.currentThread().getName());
                }
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    Log.d("haha", "current thread :" + Thread.currentThread().getName());
                }
            });

filter

//过滤1-10能整除2的数

Observable.range(1, 10)
            .filter(new AppendOnlyLinkedArrayList.NonThrowingPredicate<Integer>() {
                @Override
                public boolean test(Integer integer) {
                    return integer % 2 == 0;
                }
            })
            .subscribe(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) throws Exception {
                    Log.d("haha", "integer:" + integer);
                }
            });

groupby

Observable.range(1, 10)
            .groupBy(new Function<Integer, String>() {
                @Override
                public String apply(Integer integer) throws Exception {
                    return (integer % 2 == 0) ? "偶数组" : "奇数组";
                }
            })
            .subscribe(new Consumer<GroupedObservable<String, Integer>>() {
                @Override
                public void accept(GroupedObservable<String, Integer> stringIntegerGroupedObservable) throws Exception {
                    final String key = stringIntegerGroupedObservable.getKey();

                    stringIntegerGroupedObservable.subscribe(new Consumer<Integer>() {
                        @Override
                        public void accept(Integer integer) throws Exception {
                            Log.d("haha", integer + " is " + key);
                        }
                    });
                }
            });

take

Observable.range(1, 10)
            .take(3)
            .subscribe(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) throws Exception {
                    Log.d("haha", "integer:" + integer);
                }
            });

skip

Observable.range(1, 10)
            .skip(4)
            .subscribe(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) throws Exception {
                    Log.d("haha", "integer:" + integer);
                }
            });

scan

sacn操作符是遍历源Observable产生的结果,再按照自定义规则进行运算,依次输出每次计算后的结果给订阅者:

Observable.range(1, 10)
            .scan(new BiFunction<Integer, Integer, Integer>() {
                @Override
                public Integer apply(Integer integer, Integer integer2) throws Exception {
                    Log.d("haha", "integer = " + integer + " integer2 = " + integer2);
                    return integer + integer2;
                }
            })
            .subscribe(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) throws Exception {
                    Log.d("haha", "result :" + integer);
                }
            });

注意:第一次不参与运算

map

     //将string转化成integer
    Observable.just("33")
            .map(new Function<String, Integer>() {
                @Override
                public Integer apply(String s) throws Exception {
                    return 2017;
                }
            })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Integer>() {
                @Override
                public void accept(Integer value) throws Exception {
                    Log.d("haha", "value:" + value);
                }
            });

    Flowable.just("33")
            .map(new Function<String, Integer>() {
                @Override
                public Integer apply(String s) throws Exception {
                    return 2018;
                }
            })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) throws Exception {
                    Log.d("haha", "value:" + value);
                }
            });

flatMap:

    //给hello world前面加上字段
    Observable.just("hello","world")
            .flatMap(new Function<String, ObservableSource<String>>() {
    //第一个参数就是just 里面的参数类型,第二个参数就是ObservableSource<?> 其中?是需要转成什么类型的ObservableSource
                @Override
                public ObservableSource<String> apply(String s) throws Exception {
                    return Observable.just("good + "+s);
                }
            })
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    Log.d("haha", "s = "+s);
                }
            });

map和flatMap的区别:

map:转换成指定的对象发射出去

flatMap:转换成指定对象的ObservableSource发射出去

zip

//用途可以请求两个地址,然后拼接地址
Observable<String> stringObservable = new Observable<String>() {
        @Override
        protected void subscribeActual(Observer<? super String> observer) {
            observer.onNext("taoge");
        }
    };

    Observable<Integer> integerObservable = new Observable<Integer>() {
        @Override
        protected void subscribeActual(Observer<? super Integer> observer) {
            observer.onNext(100);
        }
    };

    Observable.zip(stringObservable, integerObservable, new BiFunction<String, Integer, String>() {
        @Override
        public String apply(String s, Integer integer) throws Exception {
            return s + integer;
        }
    }).subscribe(new Consumer<String>() {
        @Override
        public void accept(String s) throws Exception {
            Log.d("haha", "result = " + s);
        }
    });

背压(Backpressure)

我们分别创建了两根水管, 第一根水管用机器指令的执行速度来无限循环发送事件, 第二根水管随便发送点什么, 由于我们没有发送Complete事件, 因此第一根水管会一直发事件到它对应的水缸里去

Observable<String> stringObservable =Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> e) throws Exception {
            e.onNext("taoge");
        }
    }) .subscribeOn(Schedulers.io());

    Observable<Integer> integerObservable = Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> e) throws Exception {
            for (int i = 0; ; i++) {
                e.onNext(i);
            }
        }
    }).subscribeOn(Schedulers.io());

    Observable.zip(stringObservable, integerObservable, new BiFunction<String, Integer, String>() {
        @Override
        public String apply(String s, Integer integer) throws Exception {
            return s + integer;
        }
    }).observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    Log.d("haha", "result = " + s);
                }
            });

结果:内存一直在上涨

原因:
其中一个水管A发送事件特别快, 而另一个水管B 发送事件特别慢, 那就可能出现这种情况, 发得快的水管A 已经发送了1000个事件了, 而发的慢的水管B 才发一个出来, 组合了一个之后水管A 还剩999个事件, 这些事件需要继续等待水管B 发送事件出来组合, 那么这么多的事件是放在哪里的呢? 总有一个地方保存吧? 没错, Zip给我们的每一根水管都弄了一个水缸,上游发送的所有事件都放到水缸里了, 所以瞬间水缸就满了。

分析了原因怎么解决呢?

两种方案:

一是从数量上进行治理, 减少发送进水缸里的事件

二是从速度上进行治理, 减缓事件发送进水缸的速度

方案一(从数量上控制):只放我们需要的事件到水缸里

Observable<String> stringObservable =Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> e) throws Exception {
            e.onNext("taoge");
        }
    }) .subscribeOn(Schedulers.io());

    Observable<Integer> integerObservable = Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> e) throws Exception {
            for (int i = 0; ; i++) {
                e.onNext(i);
            }
        }
    }).subscribeOn(Schedulers.io()).sample(2,TimeUnit.SECONDS);

    // 这个操作符每隔指定的时间就从上游中取出一个事件发送给下游. 这里我们让它每隔2秒取一个事件给下游

    Observable.zip(stringObservable, integerObservable, new BiFunction<String, Integer, String>() {
        @Override
        public String apply(String s, Integer integer) throws Exception {
            return s + integer;
        }
    }).observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    Log.d("haha", "result = " + s);
                }
            });

方案二(从速度上控制):适当减慢发送事件的速度

Observable<String> stringObservable =Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> e) throws Exception {
            e.onNext("taoge");
        }
    }) .subscribeOn(Schedulers.io());

    Observable<Integer> integerObservable = Observable.create(new ObservableOnSubscribe<Integer>() {
        @Override
        public void subscribe(ObservableEmitter<Integer> e) throws Exception {
            for (int i = 0; ; i++) {
                Thread.sleep(2000);
                e.onNext(i);
            }
        }
    }).subscribeOn(Schedulers.io());

    Observable.zip(stringObservable, integerObservable, new BiFunction<String, Integer, String>() {
        @Override
        public String apply(String s, Integer integer) throws Exception {
            return s + integer;
        }
    }).observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    Log.d("haha", "result = " + s);
                }
            });

Flowable

http://www.jianshu.com/p/9b1304435564

Demo地址

https://github.com/wangtao520/RxDemo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值