安卓开发之RxJava入门基础

RxJava是一个异步框架,功能和之前说的EventBus是类似的,不同的是,EventBus仅是作为一种事件传递工具,事件发送后是不能做任何的数据改变,如果要改变,又要重新post一次,并且使用了EventBus的类都不能进行混淆;而RxJava里面几乎可以做任何事情,当建立起订阅关系时,可以用操作符做任何处理(比如转换数据,更改数据等),并且随着程序逻辑变得越来越复杂,RxJava依然能够保持逻辑简洁性。RxJava也可以和其他的一些第三方库例如Retrofit结合使用,处理效率更高,类似的还有RxBus、Rxpermissions等,这些之后有时间再单独学习。这次主要来学习一下RxJava的用法,它的核心思想也是观察者模式,类似于之前的EventBus,当被观察者发生变化时发送事件给观察者,可以类比成按钮点击,系统不是时刻在轮询监听按钮(被观察者)是否被点击,而是它被点击时发送一个点击事件然后系统(观察者)再去处理。

1.基本使用

1.1 首先引入依赖:

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

1.2 创建被观察者:

public class MainActivity extends AppCompatActivity {
     Disposable disposable;
     Observer<String> observer;
     Observable observable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        createObservable();//被观察者
        createObserver();//观察者
        observable.subscribe(observer);//订阅
    }
 //被观察者
 private void createObservable() {
        //method-1
        observable = Observable.create(new ObservableOnSubscribe<String>(){
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("1");
                e.onNext("2");
                e.onNext("3");
                e.onComplete();
            }
        });

       // method-2
       //observable = Observable.just("11","22","33");

        // method-3
        //String[] num = {"111","222","333"};
        //observable = Observable.fromArray(num);
    }

Observable即为被观察者,可以通过create方法得到实例,里面传入ObservableOnSubscribe< T >参数,可以理解为一个计划表,泛型T是要操作对象的类型,然后重写subscribe方法,里面写具体的计划。subscribe方法中的ObservableEmitter< String >对象的e可以理解为发射器。ObservableEmitter有三种发射的方法,分别是onNext(T value)、onError(Throwable error)、onComplete():

  • onNext:发出事件,该方法可以无限调用,Observer(观察者)都能接收到。
  • onError:事件队列异常,在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。它和onComplete互斥,Observer(观察者)只能接收到一个,且onError不可以重复调用,第二次调用就会报异常。
  • onComplete:事件队列完结,RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。当不会再有新的 onNext() 发出时,需要触发onCompleted() 方法作为标志。可以重复调用,但是Observer(观察者)只会接收一次。

这里还看到上面的method-2与method-3简化写法,这两种写法都将会依次调用onNext->…->onComplete方法,和create效果相同。

1.3 创建观察者

 private void createObserver() {
        observer = new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                disposable = d;
                Log.e("MyRxJava","onSubscribe执行了");
            }

            @Override
            public void onNext(String value) {
                if("4".equals(value)){
                    disposable.dispose();
                    return;
                }
                Log.e("MyRxJava","onNext执行了; value= " + value);
            }

            @Override
            public void onError(Throwable e) {
                Log.e("MyRxJava","onError执行了:" + e.getMessage());
            }

            @Override
            public void onComplete() {
                Log.e("MyRxJava","onComplete执行了");
            }
        };
    }

创建观察者时通过new创建接口,并实现其内部的方法,onNext、onError、onComplete都是跟被观察者发射的方法相对应的,相当于就是接收发射的事件。onSubscribe(Disposable d)里面的Disposable对象可以用来取消观察者对于被观察者的订阅关系,例如onNext方法中我们调用 disposable.dispose()取消订阅,此时被观察者发送的事件观察者就不会被接收了,大家可以把“4”改成“2”试试效果。

最后两者建立订阅关系:

  observable.subscribe(observer);

这里运行一下程序(以method-1为例):
在这里插入图片描述

2.异步使用

开头我们就提到了RxJava是一个异步框架,也就是RxJava可以在后台执行然后前台调用。但是在不指定线程的情况下,RxJava 遵循的其实是线程不变的原则,即在哪个线程调用 subscribe(),就在哪个线程生产事件;在哪个线程生产事件,就在哪个线程处理事件,也就是说线程不会产生变化,始终是在同一个。如果需要切换线程,就需要用到 Scheduler (调度器)。

2.1 Scheduler API

Scheduler相当于线程控制器,RxJava 通过它来指定每一段代码应该要运行在什么样的线程。RxJava 中内置了几个 Scheduler :

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

介绍完上面几个 Scheduler ,就可以使用subscribeOn() 和observeOn() 两个方法来对线程进行控制了。

  • subscribeOn(): 指定subscribe() 所发生的线程,即Observable.OnSubscribe被激活时所处的线程或者叫做事件产生的线程。
  • observeOn(): 指定 Subscriber 所运行在的线程或者叫做事件处理的线程。

2.2 异步

对上面的那个Demo进行修改:

public class MainActivity extends AppCompatActivity {
    Observable observable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        createObservable();//被观察者
    }

    private void createObservable() {
        observable.create(new ObservableOnSubscribe<String>(){
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("一");
                e.onNext("二");
                e.onNext("三");
                e.onComplete();
            }
        })
                .observeOn(AndroidSchedulers.mainThread())//主线程处理
                .subscribeOn(Schedulers.io())
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.e("MyRxJava","onSubscribe执行了");
                    }

                    @Override
                    public void onNext(String value) {
                        Log.e("MyRxJava","onNext执行了; value= " + value);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.e("MyRxJava","onError执行了:" + e.getMessage());
                    }

                    @Override
                    public void onComplete() {
                        Log.e("MyRxJava","onComplete执行了");
                    }
                });
    }
}

上面的代码中指定subscribeOn(Schedulers.io()) ,因此被创建的事件的内容“一”、“二”、“三”将会在 IO 线程发出;指定了observeOn
(AndroidScheculers.mainThread()) ,因此subscriber 数字的打印将发生在主线程 。这种方式常适用于后台线程取数据,主线程显示数据的场景。效果如下:在这里插入图片描述
如果只关心onNext方法里的内容,可以直接重载subscribe(Consumer<? spuer T> onNext)这个方法:

private void createObservable() {
        observable.create(new ObservableOnSubscribe<String>(){
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("一");
                e.onNext("二");
                e.onNext("三");
                e.onComplete();
            }
        })
                .observeOn(AndroidSchedulers.mainThread())//主线程处理
                .subscribeOn(Schedulers.io())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.e("MyRxJava","onNext执行了; value= " + s);
                    }
                });
    }

效果如下:
在这里插入图片描述

3.map、FlatMap操作符

最后说一下RxJava使用过程中常会使用的两个操作符。map作用简单来说就是事件对象的直接变换,让元数据改变为我们的目标数据,转换后的目标数据,将用于我们的观察者使用。FlatMap可以将一个发送事件的上游Observable变换为多个发送事件的Observables,然后将它们发射的事件合并后放进一个单独的Observable里。

map Demo:

public class MainActivity extends AppCompatActivity {
    Observable observable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        createObservable();//被观察者
    }

    private void createObservable() {
        observable.create(new ObservableOnSubscribe<Integer>(){
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                e.onNext(1);
                e.onNext(2);
                e.onNext(3);
                e.onComplete();
            }
        })
                .map(new Function<Integer, String>() {
                    @Override
                    public String apply(Integer integer) throws Exception {
                        return "value= " + integer;
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())//主线程处理
                .subscribeOn(Schedulers.io())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.e("MyRxJava",s);
                    }
                });
    }
}

在上游发送的是Integer类型, 而在下游我们接收的是String类型, 中间起转换作用的就是map操作符, 运行结果为:
在这里插入图片描述
FlatMap Demo:

public class MainActivity extends AppCompatActivity {
    Observable observable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        createObservable();//被观察者
    }

    private void createObservable() {
        observable.create(new ObservableOnSubscribe<Integer>(){
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                e.onNext(1);
                e.onNext(2);
                e.onNext(3);
                e.onComplete();
            }
        })
                .flatMap(new Function<Integer, ObservableSource<String>>() {
                    @Override
                    public ObservableSource<String> apply(Integer integer) throws Exception {
                        final List<String> list = new ArrayList<>();
                        list.add("Value " + integer);  
                        list.add("Value Test " + integer);
                        return Observable.fromIterable(list).delay(10, TimeUnit.MILLISECONDS);
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())//主线程处理
                .subscribeOn(Schedulers.io())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.e("MyRxJava",s);
                    }
                });
    }
}

flatMap中将上游发来的每个事件转换为两个新的发送String事件的Observables, 为了看到flatMap结果是无序的,所以加了10毫秒的延时, 运行结果如下:
在这里插入图片描述

参考以下文章:
RxJava2.0——从放弃到入门
给 Android 开发者的 RxJava 详解
给初学者的RxJava2.0教程(三)

猜你喜欢

转载自blog.csdn.net/weixin_42011443/article/details/108456297