Android RxJava的使用

RxJava 是一个基于观察者模式 、使用可序列化的 响应式扩展(Reactive Extensions) 来实现异步操作事件处理的库。它在 Android 开发中尤其擅长处理复杂的异步任务链、线程切换和事件流。

核心概念

  1. Observable (被观察者) : 数据源或事件源,负责发射数据或事件。它可以发射零个、一个或多个数据,以及一个成功或错误的状态。

  2. Observer (观察者) : 订阅 Observable 并对其发出的事件做出反应。它包含四个方法:

    • onSubscribe(Disposable d): 开始订阅时调用,参数 Disposable 可用于取消订阅。
    • onNext(T t): 接收到一个数据项时调用。
    • onError(Throwable e): 当 Observable 发生错误时调用。
    • onComplete(): 当 Observable 完成所有数据发射时调用。
  3. Operator (操作符) : 用于在 ObservableObserver 之间对发出的数据流进行转换、过滤、组合等操作。例如 map, filter, flatMap 等。

  4. Scheduler (调度器) : 用于控制线程。指定代码在哪个线程执行(如 IO 线程、计算线程、主线程)。

  5. Disposable: 用于取消订阅,防止内存泄漏。

  6. Single, Maybe, CompletableObservable 的特殊变种,用于特定场景。

    • Single<T>: 只发射一个成功数据或一个错误。
    • Completable: 不发射数据,只关心操作成功或失败。
    • Maybe<T>: 可能发射 0 或 1 个数据,或者一个错误。

基本使用步骤

1. 添加依赖

app/build.gradle 中添加依赖(请查看官网获取最新版本):

gradle

arduino 复制代码
dependencies {
    implementation 'io.reactivex.rxjava3:rxjava:3.1.8'
    implementation 'io.reactivex.rxjava3:rxandroid:3.0.2' // 提供Android主线程调度器

    // 或者,如果你在用 RxJava 2
    // implementation 'io.reactivex.rxjava2:rxjava:2.2.21'
    // implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
}

2. 创建一个 Observable

java

javascript 复制代码
Observable<String> observable = Observable.create(emitter -> {
    // 模拟一些工作,比如网络请求
    try {
        String data = fetchDataFromNetwork();
        emitter.onNext(data); // 发射数据
        emitter.onComplete(); // 发射完成信号
    } catch (Exception e) {
        emitter.onError(e); // 发射错误信号
    }
});

// 使用 just, from, range 等操作符快速创建
Observable.just("Hello", "RxJava"); // 依次发射 "Hello", "RxJava"
Observable.fromArray(new String[]{"A", "B", "C"}); // 从数组发射
Observable.range(1, 5); // 发射 1, 2, 3, 4, 5

3. 创建一个 Observer 并订阅

java

less 复制代码
Observer<String> observer = new Observer<String>() {
    @Override
    public void onSubscribe(@NonNull Disposable d) {
        // 订阅开始,可以在这里保存 Disposable 以便后续取消
        Log.d("RxJava", "onSubscribe");
    }

    @Override
    public void onNext(@NonNull String s) {
        // 处理接收到的数据
        Log.d("RxJava", "onNext: " + s);
    }

    @Override
    public void onError(@NonNull Throwable e) {
        // 处理错误
        Log.e("RxJava", "onError: ", e);
    }

    @Override
    public void onComplete() {
        // 任务完成
        Log.d("RxJava", "onComplete");
    }
};

// 建立订阅关系
observable.subscribe(observer);

4. 使用 Lambda 表达式简化

通常我们会用 Lambda 来简化 Observer 的创建:

java

less 复制代码
Disposable disposable = observable
    .subscribe(
        s -> Log.d("RxJava", "onNext: " + s), // onNext
        throwable -> Log.e("RxJava", "onError: ", throwable), // onError
        () -> Log.d("RxJava", "onComplete") // onComplete
    );

// 保存 disposable,在合适的时候(如 Activity 的 onDestroy)取消订阅
// disposable.dispose();

核心操作符示例

操作符是 RxJava 强大功能的体现。

  1. map() : 转换发射的数据类型。

    java

    vbnet 复制代码
    Observable.just(1, 2, 3)
        .map(number -> "Number is: " + number) // 将 Integer 转换为 String
        .subscribe(s -> Log.d("TAG", s));
    // 输出: Number is: 1, Number is: 2, Number is: 3
  2. filter() : 过滤数据。

    java

    typescript 复制代码
    Observable.just(1, 2, 3, 4, 5)
        .filter(number -> number % 2 == 0) // 只允许偶数通过
        .subscribe(number -> Log.d("TAG", "" + number));
    // 输出: 2, 4
  3. flatMap() : 将一个发射数据的 Observable 变换为多个 Observables,然后将它们扁平化为一个单独的 Observable。非常适合用于链式异步操作(如先请求 A,再用 A 的结果请求 B)。

    java

    less 复制代码
    Observable.just("user_id_123")
        .flatMap(userId -> fetchUserDetailsFromNetwork(userId)) // fetchUserDetailsFromNetwork 返回一个 Observable<User>
        .subscribe(user -> updateUI(user));
  4. subscribeOn() & observeOn() : 线程控制的核心

    • subscribeOn(): 指定 Observable 在哪个线程执行(即数据发射的线程)。多次调用只有第一次有效
    • observeOn(): 指定 Observer 在哪个线程接收处理数据(即数据消费的线程)。可以多次调用,改变后续操作的线程

    java

    kotlin 复制代码
    Observable.create(emitter -> {
            // 在 IO 线程执行(执行耗时操作,如网络请求、读文件)
            String data = doHeavyWork();
            emitter.onNext(data);
            emitter.onComplete();
        })
        .subscribeOn(Schedulers.io()) // 指定上游在 IO 线程执行
        .observeOn(AndroidSchedulers.mainThread()) // 指定下游在主线程接收
        .subscribe(data -> {
            // 在主线程更新 UI
            textView.setText(data);
        });

    Android 中的实践与注意事项

1. 防止内存泄漏:管理 Disposable

在 Android 中,ActivityFragment 被销毁后,如果异步操作还在执行并尝试更新 UI,就会导致内存泄漏或崩溃。必须及时取消订阅。

推荐使用 CompositeDisposable 来管理多个 Disposable

java

scala 复制代码
public class MainActivity extends AppCompatActivity {

    private CompositeDisposable compositeDisposable = new CompositeDisposable();

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

        Disposable disposable = Observable.just("Hello")
                .delay(10, TimeUnit.SECONDS) // 模拟一个长时间运行的任务
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(s -> textView.setText(s));

        // 将 Disposable 添加到 CompositeDisposable 中统一管理
        compositeDisposable.add(disposable);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 在生命周期结束时取消所有订阅
        compositeDisposable.clear(); // 或 compositeDisposable.dispose()
    }
}

2. 与 Retrofit 结合进行网络请求

Retrofit 原生支持返回 Observable 类型,这是最常见的用法。

接口定义:

java

less 复制代码
public interface ApiService {
    @GET("user/{id}")
    Observable<User> getUser(@Path("id") String userId);
}

使用:

java

less 复制代码
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.example.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava3CallAdapterFactory.create()) // 关键!添加 RxJava 调用适配器
        .build();

ApiService apiService = retrofit.create(ApiService.class);

compositeDisposable.add(
    apiService.getUser("123")
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            user -> updateUI(user),
            throwable -> showError(throwable)
        )
);

3. 处理界面事件(RxBinding)

可以使用 RxBinding 库将 Android 的 UI 事件(如点击、文本变化)转换为 Observable。

gradle

arduino 复制代码
implementation 'com.jakewharton.rxbinding4:rxbinding:4.0.0'

java

scss 复制代码
// 监听按钮点击
Disposable clickDisposable = RxView.clicks(button)
        .throttleFirst(500, TimeUnit.MILLISECONDS) // 防止连续点击,500ms内只取第一次
        .subscribe(unit -> {
            // 处理点击事件
            performAction();
        });
compositeDisposable.add(clickDisposable);

// 监听 EditText 文本变化
Disposable textDisposable = RxTextView.textChanges(editText)
        .debounce(300, TimeUnit.MILLISECONDS) // 防抖,停止输入 300ms 后才发射
        .filter(charSequence -> charSequence.length() > 3)
        .subscribe(charSequence -> {
            // 处理搜索建议等
            showSuggestions(charSequence.toString());
        });
compositeDisposable.add(textDisposable);

总结

场景 解决方案
异步任务(网络、数据库) Observable + subscribeOn(Schedulers.io())
更新 UI observeOn(AndroidSchedulers.mainThread())
链式异步任务 flatMap 操作符
事件转换/过滤 map, filter 等操作符
防止内存泄漏 CompositeDisposable 并在生命周期方法中清理
网络请求 Retrofit + RxJava Call Adapter
UI 事件处理 RxBinding 库

RxJava 的学习曲线稍陡,但一旦掌握,它能极大地简化异步代码的编写,让逻辑变得清晰且易于维护。先从理解观察者模式线程调度开始,然后逐步熟悉常用的操作符。

相关推荐
我要升天!6 分钟前
MySQL表的内连和外连
android·mysql·adb
dora24 分钟前
Flutter中dart和原生代码的通信之MethodChannel
android·flutter
路上^_^36 分钟前
安卓基础组件031-Retrofit 网络请求框架
android
计算机毕业设计小帅7 小时前
【2026计算机毕业设计】基于Springboot的Android校园周边美食汇系统
android·spring boot·课程设计
每次的天空7 小时前
Android-MVX技术总结
android
Digitally10 小时前
如何备份和恢复安卓设备2025
android
ClassOps11 小时前
腾讯CODING Maven的aar制品添加上传流程
android·java·maven
ClassOps11 小时前
基于腾讯CODING Maven的Android库发布
android·java·maven
路上^_^12 小时前
安卓基础组件024-底部导航栏
android
加菲猫86012 小时前
文件上传简单的绕过总结
android