You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:05:47