RxJava Timer与Retrofit代码优化:实现延迟显示ProgressDialog
优化RxJava加载Dialog逻辑:告别嵌套反模式
嘿,我完全懂你为啥觉得这段代码是反模式——嵌套的Observable订阅把逻辑搅得一团糟,不仅难维护,还容易埋下内存泄漏或者线程安全的坑。咱们来把它改得更清晰、更健壮!
原代码的核心问题
- 内部嵌套了
Observable.timer的订阅,却没把它加入CompositeDisposable,很容易导致内存泄漏 - 加载状态(
mIsLoading)和Dialog显示逻辑耦合在一起,可读性差 - Dialog的显示/关闭逻辑分散在多个回调里,容易出现漏关或者重复显示的问题
优化后的实现思路
我们把「延迟显示Dialog」和「API请求」拆成两个独立的Disposable,统一用CompositeDisposable管理。核心逻辑是:启动一个2秒的延迟任务,一旦API请求完成(不管成功还是失败),立即取消这个延迟任务,并关闭可能已经显示的Dialog。
优化后的代码
CompositeDisposable disposable = getCompositeDisposable(); // 标记开始加载 mIsLoading.set(true); // 1. 创建延迟2秒显示ProgressDialog的任务 Disposable dialogDelayDisposable = Observable.timer(2000, TimeUnit.MILLISECONDS) .subscribeOn(scheduler) .observeOn(AndroidSchedulers.mainThread()) .subscribe(__ -> { // 只有仍在加载且需要显示Dialog时才弹出 if (mIsLoading.get() && isShowProgressDialog) { progressDialog.show(); } }); // 把延迟任务加入CompositeDisposable,避免内存泄漏 disposable.add(dialogDelayDisposable); // 2. 执行API请求 Disposable apiRequestDisposable = mRemoteUseCase.sendData(profileInfo) .subscribeOn(scheduler) .observeOn(AndroidSchedulers.mainThread()) // 请求结束(成功/失败/取消)时统一处理收尾逻辑 .doAfterTerminate(() -> { mIsLoading.set(false); // 取消延迟任务,防止Dialog在请求完成后还弹出 dialogDelayDisposable.dispose(); // 关闭已经显示的Dialog if (progressDialog != null && progressDialog.isShowing()) { progressDialog.dismiss(); } }) .subscribe(remoteResponse -> { // 请求成功的处理逻辑 dataManager.setProfile(profile); }, throwable -> { // 请求失败的处理逻辑 listener.onError(throwable); Dialog errorDialog = DialogFactory.createSimpleOkErrorDialog(context, "Error"); errorDialog.show(); }); // 把API请求任务加入CompositeDisposable disposable.add(apiRequestDisposable);
优化点说明
- 解耦逻辑:把Dialog延迟任务和API请求分开,代码结构更清晰,可读性拉满
- 内存安全:两个Disposable都加入了
CompositeDisposable,在页面销毁时调用disposable.clear()就能彻底清理,避免内存泄漏 - 统一收尾:用
doAfterTerminate统一处理加载状态重置、延迟任务取消和Dialog关闭,不管请求成功还是失败都能执行,不会遗漏 - 线程安全:
mIsLoading用AtomicBoolean保证多线程下的状态正确性,Dialog的操作都切换到了主线程,符合Android UI线程的要求
额外注意事项
- 确保
progressDialog是在主线程初始化的,因为show()和dismiss()必须在UI线程调用 - 在Activity/Fragment的
onDestroy()方法里一定要调用getCompositeDisposable().clear(),避免内存泄漏和Dialog的空指针异常
内容的提问来源于stack exchange,提问作者A. Oktay
相关产品推荐
相关产品推荐

