RxJava学习笔记

RxJava个人学习笔记

主要内容包含以下部分:

  • RxJava是什么
  • HelloWorld
  • 变换
  • 操作符
  • 切换线程

RxJava是什么

最初学习使用RxJava的时候,很难理解RxJava到底是什么东西,其实耐心多看几遍就会理解了。RxJava其实就是一个处理异步事件的库。作为一个Android开发者肯定遇到过子线程请求数据,主线程更新UI的这样的需求,,使用RxJava就可以简单明了的完成这样的功能。

HelloWorld

首先在module的gradle文件里添加依赖(Android Studio3.0,Gradle3.0之后compile变为implementation)

    implementation 'io.reactivex.rxjava2:rxjava:2.1.3'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

RxJava最核心的两个东西是Observable(被观察者)和Observer(观察者)。被观察者发出一系列的事件之后,观察者根据这些事件做出处理。
首先创建一个Observable对象

    Observable<String> observable=Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
           e.onNext("Hello World");
            }

这里被观察者发出了一条消息,这条消息会传到观察者那里处理。

Observer<String> observer=new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
            }
            @Override
            public void onNext(String s) {
                Log.v("rxjava",s);
            }
            @Override
            public void onError(Throwable e) {
            }
            @Override
            public void onComplete() {
            }
        };

然后将observer订阅observable

 observable.subscribe(observer);

运行之后Log显示如下:

10-16 11:06:33.817 3095-3095/com.wangguan.demos V/rxjava: Hello World

上边的写法也可以串起来写成链式的操作:

        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext("Hello");
                emitter.onNext("World");
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
            }
            @Override
            public void onNext(String s) {
                Log.v("rxjava",s);
            }
            @Override
            public void onError(Throwable e) {
            }
            @Override
            public void onComplete() {
            }
        });

是不是觉得为了写一行代码要实现这么多的接口很麻烦,subscribe也可以调用简单的Observer:Consumer。Consumer只需要实现Observer的onNext即可。

   Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext("Hello");
                emitter.onNext("World");
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Log.v("rxjava",s);
            }
        });

Observable还可以传入数组形式的参数,比如

String[] words = {"Hello", "World"};
Observable observable = Observable.fromArray(words);

这样的写法等价于上边的

      Observable<String> observable=Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("Hello");
                e.onNext("World");
                e.onNext("RXJAVA");
            }

变换

有时候代码里面传入的参数和需要使用的数据类型不同,比如需要传入int类型的drawable的id得到Bitmap的图片。这时候怎么写呢?当然可以在onNext方法中通过int得到Bitmap然后显示在ImageView中。如下:

 Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(R.mipmap.ic_launcher);
            }
        }).subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(Disposable d) {
            }
            @Override
            public void onNext(Integer id) {
                Bitmap bmp = BitmapFactory.decodeResource(getResources(), id);
                imageView.setImageBitmap(bmp);
            }
            @Override
            public void onError(Throwable e) {
            }
            @Override
            public void onComplete() {
            }
        });

但是RxJava最强大的地方是可以把逻辑写的简明。如果在onNext得到的就是Bitmap 是不是更好呢?当然也是可以的。使用map变换符就可以了。

Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(R.mipmap.ic_launcher);
            }
        }).map(new Function<Integer, Bitmap>() {
            @Override
            public Bitmap apply(Integer id) throws Exception {
                Bitmap bmp = BitmapFactory.decodeResource(getResources(), id);
                return bmp;
            }
        }).subscribe(new Observer<Bitmap>() {
            @Override
            public void onSubscribe(Disposable d) {
            }
            @Override
            public void onNext(Bitmap bmp) {
                imageView.setImageBitmap(bmp);
            }
            @Override
            public void onError(Throwable e) {
            }
            @Override
            public void onComplete() {
            }
        });

首先R.mipmap.ic_launcher会在map里做处理,通过Function将Integer转成Bitmap,然后在onNext里得到的就是Bitmap类型的数据了。

操作符

操作符是为了解决对Observable对象的变换的问题,操作符用于在Observable和最终的Subscriber之间修改Observable发出的事件。
常见的操作符有:

  • fromArray
  • map
  • flatMap
  • filter
  • take
  • doOnNext

切换线程

在实际Android开发中,网络请求是最常见的处理之一。一般都是在子线程中请求数据,然后在主线程中修改UI,原因都懂的。那么刚才修改图片的例子是不是一直在主线程中运行呢?刚才的代码修改一下,打印一下线程名称。如下:

 Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                Log.v("rxjava",Thread.currentThread().getName());
                emitter.onNext(R.mipmap.ic_launcher);
            }
        }).map(new Function<Integer, Bitmap>() {
            @Override
            public Bitmap apply(Integer id) throws Exception {
                Log.v("rxjava",Thread.currentThread().getName());
                Bitmap bmp = BitmapFactory.decodeResource(getResources(), id);
                return bmp;
            }
        }).subscribe(new Consumer<Bitmap>() {
            @Override
            public void accept(Bitmap bitmap) throws Exception {
                Log.v("rxjava",Thread.currentThread().getName());
                imageView.setImageBitmap(bitmap);
            }
        });

日志为:

10-19 05:53:56.124 4187-4187/com.wangguan.demos V/rxjava: main
10-19 05:53:56.124 4187-4187/com.wangguan.demos V/rxjava: main
10-19 05:53:56.130 4187-4187/com.wangguan.demos V/rxjava: main

根据log的输出显然全部的处理都是在主线程中运行的。Android4.0以后,如果直接在主线程中发起网络请求程序直接会发生异常,那么应该怎么样呢?

 Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                Log.v("rxjava1", Thread.currentThread().getName());
                emitter.onNext("https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png");
            }
        }).subscribeOn(Schedulers.io())
                .map(new Function<String, Bitmap>() {
                    @Override
                    public Bitmap apply(String imageUrl) throws Exception {
                        Log.v("rxjava2", Thread.currentThread().getName());
                        URL url = new URL(imageUrl);
                        Bitmap bmp = BitmapFactory.decodeStream(url.openStream());
                        return bmp;
                    }
                }).observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Bitmap>() {
                    @Override
                    public void accept(Bitmap bitmap) throws Exception {
                        Log.v("rxjava3", Thread.currentThread().getName());
                        imageView.setImageBitmap(bitmap);
                    }
                });

这里多了两行代码:

subscribeOn(Schedulers.io())
observeOn(AndroidSchedulers.mainThread())

日志如下:

10-19 06:51:05.850 5813-6007/com.wangguan.demos V/rxjava1: RxCachedThreadScheduler-2
10-19 06:51:05.851 5813-6007/com.wangguan.demos V/rxjava2: RxCachedThreadScheduler-2
10-19 06:51:05.980 5813-5813/com.wangguan.demos V/rxjava3: main

看了log之后,这两行代码的作用就很明了了:起到了切换线程的作用。
subscribeOn把被观察者的线程切换到了IO线程。
observeOn把观察者的线程切换到了主线程。
所以把String转成Bitmap的处理也在IO线程中运行。

在RxJava中, 已经内置了很多线程选项,比如

  • Schedulers.io() 代表io操作的线程, 通常用于网络,读写文件等io密集型的操作
  • Schedulers.computation() 代表CPU计算密集型的操作, 例如需要大量计算的操作
  • Schedulers.newThread() 代表一个常规的新线程
  • AndroidSchedulers.mainThread() 代表Android的主线程

参考文档:
给初学者的RxJava2.0教程
给 Android 开发者的 RxJava 详解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值