RxJava Android实战:18个生产级示例深度解析
前言:为什么需要RxJava Android示例?
在Android开发中,异步操作、线程管理和事件处理一直是开发者的痛点。传统的AsyncTask、Handler和Thread管理复杂且容易出错。RxJava(Reactive Extensions for Java)通过响应式编程范式,为Android开发带来了革命性的解决方案。
RxJava-Android-Samples项目提供了18个精心设计的实战示例,涵盖了从基础并发控制到高级数据流处理的各个方面。本文将深度解析这些示例的核心实现原理和最佳实践。
核心概念速览
在深入示例之前,先了解RxJava的几个核心概念:
| 概念 | 说明 | Android中的典型应用 |
|---|---|---|
| Observable(可观察对象) | 数据源,发射数据项 | 网络请求、用户输入、传感器数据 |
| Observer(观察者) | 消费数据项 | UI更新、数据处理 |
| Scheduler(调度器) | 控制线程执行 | 后台线程执行、主线程更新 |
| Operator(操作符) | 数据转换和处理 | 过滤、映射、组合数据流 |
1. 后台工作与并发控制(Schedulers)
问题场景
长时间运行的I/O操作阻塞UI线程,导致应用无响应。
RxJava解决方案
Observable.just(true)
.subscribeOn(Schedulers.io()) // 在IO线程执行
.observeOn(AndroidSchedulers.mainThread()) // 在主线程观察结果
.map(aBoolean -> {
_doSomeLongOperation_thatBlocksCurrentThread();
return aBoolean;
})
.subscribe(new DisposableObserver<Boolean>() {
@Override
public void onNext(Boolean bool) {
_log(String.format("onNext with return value \"%b\"", bool));
}
@Override
public void onError(Throwable e) {
_log(String.format("Boo! Error %s", e.getMessage()));
}
@Override
public void onComplete() {
_log("On complete");
}
});
线程调度策略对比
| 调度器类型 | 适用场景 | 特点 |
|---|---|---|
Schedulers.io() | I/O密集型操作 | 无界线程池,适合网络、文件操作 |
Schedulers.computation() | CPU密集型计算 | 固定大小线程池,适合数据处理 |
AndroidSchedulers.mainThread() | UI更新 | 在主线程执行,用于更新界面 |
Schedulers.newThread() | 长时间任务 | 每次创建新线程,慎用 |
2. 实时搜索优化(Debounce操作符)
问题场景
用户输入时频繁触发搜索请求,造成性能浪费和无效请求。
传统实现痛点
// 传统实现 - 每次输入都触发搜索
editText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
performSearch(s.toString()); // 每次输入都搜索
}
});
RxJava优化方案
RxTextView.textChangeEvents(_inputSearchText)
.debounce(400, TimeUnit.MILLISECONDS) // 400毫秒防抖
.filter(changes -> !TextUtils.isEmpty(changes.text().toString()))
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableObserver<TextViewTextChangeEvent>() {
@Override
public void onNext(TextViewTextChangeEvent event) {
_log(format("Searching for %s", event.text().toString()));
performSearch(event.text().toString());
}
});
防抖机制效果对比
3. Retrofit网络请求集成
基础网络请求
_githubService.contributors(username, repo)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableObserver<List<Contributor>>() {
@Override
public void onNext(List<Contributor> contributors) {
// 处理贡献者列表
}
});
复杂数据流处理(flatMap + zip)
_githubService.contributors(username, repo)
.flatMap(Observable::fromIterable) // 将List展开为单个Contributor
.flatMap(contributor -> {
Observable<User> userObservable = _githubService.user(contributor.login);
return Observable.zip(userObservable, Observable.just(contributor), Pair::new);
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableObserver<Pair<User, Contributor>>() {
@Override
public void onNext(Pair<User, Contributor> pair) {
// 处理用户和贡献者的组合数据
}
});
网络请求操作符对比
| 操作符 | 用途 | 适用场景 |
|---|---|---|
flatMap | 转换并展平Observable | 嵌套网络请求 |
zip | 组合多个Observable | 并行请求后合并结果 |
concat | 顺序执行Observable | 有依赖关系的串行请求 |
merge | 合并多个Observable | 并行执行无依赖请求 |
4. 表单验证(combineLatest)
多字段实时验证
Observable<Boolean> emailValid = RxTextView.textChanges(_emailEditText)
.map(email -> isValidEmail(email.toString()));
Observable<Boolean> passwordValid = RxTextView.textChanges(_passwordEditText)
.map(password -> isValidPassword(password.toString()));
Observable<Boolean> numberValid = RxTextView.textChanges(_numberEditText)
.map(number -> isValidNumber(number.toString()));
Observable.combineLatest(emailValid, passwordValid, numberValid,
(email, pwd, num) -> email && pwd && num)
.subscribe(valid -> {
_submitButton.setEnabled(valid);
_showValidationResult(valid);
});
5. 高级模式:指数退避重试
网络请求失败重试策略
Observable.fromCallable(() -> performNetworkCall())
.retryWhen(new RetryWithDelay(5, 1000, throwable -> {
if (throwable instanceof IOException) {
return true; // 只对IO异常重试
}
return false;
}))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(response -> {
// 处理成功响应
}, error -> {
// 处理最终错误
});
指数退避算法实现
public class RetryWithDelay implements Function<Observable<Throwable>, Observable<?>> {
private final int maxRetries;
private final int retryDelayMillis;
private final Function<Throwable, Boolean> retryCondition;
private int retryCount;
@Override
public Observable<?> apply(Observable<Throwable> attempts) {
return attempts.flatMap((Throwable throwable) -> {
if (++retryCount < maxRetries && retryCondition.apply(throwable)) {
int delay = retryDelayMillis * (int) Math.pow(2, retryCount - 1);
return Observable.timer(delay, TimeUnit.MILLISECONDS);
}
return Observable.error(throwable);
});
}
}
6. 数据缓存策略(Pseudo Cache)
多级缓存实现方案
// 1. concat - 顺序执行,先缓存后网络
Observable.concat(memoryCache, networkCall)
.firstElement()
.subscribe(contributor -> showData(contributor));
// 2. concatEager - 并行开始,顺序输出
Observable.concatEager(Arrays.asList(memoryCache, networkCall))
.firstElement()
.subscribe(contributor -> showData(contributor));
// 3. publish + merge + takeUntil - 最优方案
networkCall.publish(network ->
Observable.merge(memoryCache.takeUntil(network), network))
.firstElement()
.subscribe(contributor -> showData(contributor));
缓存策略对比分析
| 策略 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| concat | 实现简单 | 网络请求必须等待缓存完成 | 缓存很快的场景 |
| concatEager | 并行执行 | 可能显示陈旧数据 | 需要快速响应的场景 |
| publish+merge | 最优性能 | 实现复杂 | 生产环境推荐 |
7. 页面旋转数据持久化
Worker Fragment模式
public class RotationPersistWorkerFragment extends Fragment {
private PublishSubject<Integer> subject;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true); // 关键:保留实例
subject = PublishSubject.create();
Observable.interval(1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.computation())
.subscribe(subject::onNext);
}
public Observable<Integer> getObservable() {
return subject;
}
}
8. RxBus事件总线
基于Subject的事件总线
public class RxBus {
private final Subject<Object> bus = PublishSubject.create().toSerialized();
public void send(Object event) {
bus.onNext(event);
}
public <T> Observable<T> toObservable(Class<T> eventType) {
return bus.ofType(eventType);
}
}
// 使用示例
rxBus.toObservable(ClickEvent.class)
.debounce(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> handleClick(event));
最佳实践总结
内存管理
// 使用CompositeDisposable管理多个订阅
private CompositeDisposable disposables = new CompositeDisposable();
@Override
public void onDestroy() {
super.onDestroy();
disposables.dispose(); // 避免内存泄漏
}
错误处理
Observable.just("data")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
data -> { /* 处理数据 */ },
error -> {
Timber.e(error, "操作失败");
showErrorToast(error.getMessage());
},
() -> { /* 完成处理 */ }
);
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



