RxJava Android实战:18个生产级示例深度解析

RxJava Android实战:18个生产级示例深度解析

【免费下载链接】RxJava-Android-Samples Learning RxJava for Android by example 【免费下载链接】RxJava-Android-Samples 项目地址: https://gitcode.com/gh_mirrors/rx/RxJava-Android-Samples

前言:为什么需要RxJava Android示例?

在Android开发中,异步操作、线程管理和事件处理一直是开发者的痛点。传统的AsyncTaskHandlerThread管理复杂且容易出错。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());
        }
    });

防抖机制效果对比

mermaid

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());
        },
        () -> { /* 完成处理 */ }
    );

【免费下载链接】RxJava-Android-Samples Learning RxJava for Android by example 【免费下载链接】RxJava-Android-Samples 项目地址: https://gitcode.com/gh_mirrors/rx/RxJava-Android-Samples

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

抵扣说明:

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

余额充值