RxJava手把手入门教程(1)---RxJava的基本用法

最近维护了一个Android app项目,主要用于工厂测试。因为我本身是一名嵌入式系统工程师,仅仅我自学过一段时间Android应用,没办法只能硬着头皮上了。在理解代码架构的时候,看到一段代码甚是头疼,产生疑问,为什么把代码写的可读性这么差,研究了好久没看懂这段代码是如何运行的。经过多方了解才知道这个是RxJava,但是看网上对它的评价很高,索性多花了些时间研究它,最终才发现是啪啪打脸。在此记录学习过程,相信你一定可以学会它。(因为在java方面来说,我实在是太菜了,不是我的强项哇)

什么是RxJava

当我们处理异步任务时,经常会遇到需要等待某个任务完成后再执行下一个任务的情况。RxJava 是一种用于处理异步任务的库,它提供了一种简洁而强大的方式来处理这种情况。
RxJava 的核心概念是 Observable(可观察对象)和 Observer(观察者)。Observable 可以发出一系列的事件,而 Observer 则可以订阅这些事件并对其进行处理。
使用 RxJava,我们可以创建一个 Observable 对象,然后通过一系列的操作符对其进行转换、过滤、组合等操作,最后将结果发送给 Observer 进行处理。
例如,我们可以创建一个 Observable 对象来监听网络请求,当网络请求完成时,Observable 就会发出一个事件,然后我们可以通过订阅这个 Observable 来处理这个事件,比如更新 UI 或者保存数据。
RxJava 还提供了丰富的操作符,例如 map、filter、flatMap 等,可以帮助我们对数据进行转换和处理。这些操作符可以链式调用,形成一个任务链,使得我们可以更加灵活地处理异步任务。
总的来说,RxJava 提供了一种优雅而强大的方式来处理异步任务,使得我们可以更加方便地编写响应式、可组合的代码,提高代码的可读性和可维护性。

步骤一: 添加依赖项

在android项目下面,F:\android_app\learn_project\DebugApp\app\build.gradle文件中添加依赖:

dependencies {
	...
    implementation 'io.reactivex.rxjava3:rxjava:3.1.1'
	...
}

步骤二 :创建 Observable

RxJava 的核心是 Observable 类。Observable 代表一个可观察的数据源,它可以发射(emit)一系列的数据项。
以下是创建一个简单的 Observable 的示例:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Observable<String> observable = Observable.just("RxJava", "Hello", "MasterLi");
        observable.subscribe(data -> Log.d(TAG, data));

    }

最终打印结果如下:
在这里插入图片描述
在上述示例中,我们使用 Observable.just() 创建了一个发射三个字符串数据项的 Observable。然后,我们通过 subscribe() 方法订阅这个 Observable,并在每个数据项上打印出来。

步骤三:操作符

RxJava 提供了许多操作符,用于对 Observable 进行转换、过滤、组合等操作。以下是一些常用的操作符:

  • map():将 Observable 发射的每个数据项进行转换。
  • filter():过滤掉不符合条件的数据项。
  • flatMap():将 Observable 发射的每个数据项转换为一个新的 Observable,然后将这些 Observables 的数据合并成一个 Observable。
  • zip():将多个 Observable 的数据项按顺序进行合并。
    以下是一个使用操作符的示例:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Observable<Integer> observable = Observable.range(1, 5)
                .map(num -> num * 2)
                .filter(num -> num > 5);

        observable.subscribe(data -> Log.d(TAG, String.valueOf(data)));

    }

在上述示例中,我们使用 Observable.range() 创建一个发射整数序列的 Observable。然后,我们使用 map() 操作符将每个数据项乘以 2,使用 filter() 操作符过滤掉小于等于 5 的数据项。

最后,我们通过 subscribe() 方法订阅这个 Observable,并打印出过滤后的数据项。打印结果如下:
在这里插入图片描述

步骤四:观察者

除了创建 Observable,你还需要创建一个观察者(Observer),用于接收 Observable 发射的数据项。

以下是一个简单的观察者的示例:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Observable<String> observable = Observable.just("Hello", "RxJava");

        Observer<String> observer = new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, "onSubscribe");
            }

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

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "onError: " + e);
            }

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

        observable.subscribe(observer);
    }

在上述示例中,我们创建了一个观察者,并实现了 Observer 接口的各个方法。在 onSubscribe() 方法中,我们可以执行一些初始化操作。在 onNext() 方法中,我们处理每个发射的数据项。在 onError() 方法中,我们处理错误情况。在 onComplete() 方法中,我们处理 Observable 完成的情况。
最后,我们通过 subscribe() 方法将观察者订阅到 Observable 上。
打印结果如下:
在这里插入图片描述

步骤五:调度器(Schedulers)

在 RxJava 中,调度器(Schedulers)用于控制 Observable 的执行线程。通过使用不同的调度器,你可以指定 Observable 的执行在哪个线程上进行。以下是一些常用的调度器:

  • Schedulers.io():用于 I/O 操作,例如读写文件、网络请求等。
  • Schedulers.computation():用于计算密集型操作,例如数学计算等。
  • Schedulers.newThread():在每次订阅时创建一个新的线程。
  • Schedulers.single():在一个单一的线程上执行操作。
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Observable.just("Hello", "RxJava")
                .subscribeOn(Schedulers.io())
                .observeOn(Schedulers.newThread())
                .subscribe(data -> Log.d(TAG, data));

        // 等待一段时间,以便观察输出
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

在上述示例中,我们使用 subscribeOn() 操作符指定了 Observable 的执行线程为 Schedulers.io(),这意味着 Observable 的数据发射将在 I/O 线程上进行。然后,我们使用 observeOn() 操作符指定了观察者的执行线程为 Schedulers.newThread(),这意味着观察者的数据处理将在一个新的线程上进行。

步骤六:处理错误

在 RxJava 中,你可以通过 onError() 方法处理 Observable 发生的错误。当 Observable 发生错误时,它将调用观察者的 onError() 方法,并传递一个 Throwable 对象,表示发生的错误。
以下是一个处理错误的示例:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Observable<Integer> observable = Observable.just(1, 2, 3, 4, 5)
                .map(num -> {
                    if (num == 3) {
                        throw new RuntimeException("Error");
                    }
                    return num;
                });

        observable.subscribe(data ->
                        Log.d(TAG, String.valueOf(data)),
                        error -> Log.e(TAG, "receive a error", error)
        );
    }

在上述示例中,我们使用 map() 操作符对 Observable 发射的每个数据项进行转换。如果数据项的值等于 3,我们抛出一个运行时异常。
在 subscribe() 方法中,我们传递了两个参数。第一个参数是处理正常数据项的回调,第二个参数是处理错误的回调。当 Observable 发射到值为 3 的数据项时,它将调用错误回调,并打印出错误消息。以下是打印结果:
在这里插入图片描述

步骤七:取消订阅

在 RxJava 中,你可以使用 Disposable 对象来取消订阅 Observable。当你不再需要接收 Observable 的数据时,可以调用 dispose() 方法来取消订阅。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Observable<Long> observable = Observable.interval(1, TimeUnit.SECONDS);

        Disposable disposable = observable.subscribe(data -> Log.d(TAG, String.valueOf(data)));

        // 等待一段时间后取消订阅
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        disposable.dispose();
    }

在上述示例中,我们使用 Observable.interval() 创建一个每秒发射一个递增的长整型数据项的 Observable。然后,我们通过 subscribe() 方法订阅这个 Observable,并将返回的 Disposable 对象保存起来。
在等待了 5 秒后,我们调用 dispose() 方法来取消订阅 Observable。以下是打印结果:
在这里插入图片描述

步骤 八:组合操作符

RxJava 提供了一些组合操作符,用于将多个 Observable 组合在一起,以便进行更复杂的操作。

以下是一些常用的组合操作符:

  • merge():将多个 Observable 的数据项合并成一个 Observable,按照数据项的发射顺序进行合并。
  • concat():将多个 Observable 的数据项合并成一个 Observable,按照 Observable 的顺序进行合并。
  • zip():将多个 Observable 的数据项按顺序进行合并,每个数据项是来自每个 Observable 的数据项的组合。
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Observable<String> observable1 = Observable.just("Hello");
        Observable<String> observable2 = Observable.just("RxJava");

        Observable<String> combinedObservable = Observable.zip(observable1, observable2, (s1, s2) -> s1 + " " + s2);

        combinedObservable.subscribe(data -> Log.d(TAG, data));
    }

在上述示例中,我们使用 Observable.just() 创建两个发射字符串数据项的 Observable。然后,我们使用 zip() 操作符将这两个 Observable 的数据项按顺序进行合并,并通过一个 lambda 表达式将两个数据项拼接起来。

最后,我们通过 subscribe() 方法订阅合并后的 Observable,并打印出合并后的数据项。
在这里插入图片描述

步骤九:背压(Backpressure)

在处理大量数据或处理速度不匹配的情况下,背压机制可以帮助控制数据的流动,以避免内存溢出或数据丢失。

RxJava 提供了一些背压策略,用于处理背压情况。以下是一些常用的背压策略:

  • onBackpressureBuffer():缓冲所有数据项,直到订阅者准备好接收。
  • onBackpressureDrop():丢弃无法及时处理的数据项。
  • onBackpressureLatest():只保留最新的数据项,丢弃旧的数据项。
  • onBackpressureError():当无法及时处理数据项时,抛出 MissingBackpressureException 错误。
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Flowable.range(1, 10)
                .observeOn(Schedulers.computation())
                .subscribe( data ->
                                Log.d(TAG, String.valueOf(data)),
                                Throwable::printStackTrace
                );

        // 等待一段时间,以便观察输出
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

在上述示例中,我们使用 Flowable.range() 创建一个发射整数序列的 Flowable。然后,我们使用 observeOn() 操作符指定了数据处理的线程为 Schedulers.computation(),这意味着数据的处理将在计算密集型线程上进行。

最后,我们通过 subscribe() 方法订阅这个 Flowable,并打印出数据项。由于没有指定背压策略,默认使用的是 onBackpressureError(),当数据处理速度不匹配时,将抛出 MissingBackpressureException 错误。

步骤十:学习资料

其实学到这里,我认为基本使用已经够了。但是如果想要更加深入的学习,下面有一些资料可以参考。

此外,还有一些优秀的书籍和在线课程可供学习:

  • 《Reactive Programming with RxJava》 - 作者:Tomasz Nurkiewicz 和 Ben Christensen
  • 《RxJava Essentials》 - 作者:Ivan Morgillo
  • Udemy 上的 RxJava 课程

好了,到这里分享以及总结就结束了,后面我还会想抽时间,研究一下RxJava的原理。就当后续啦~拜拜喽

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是李校长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值