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

Android:点击刷新按钮后ProgressDialog未即时显示问题排查(不使用AsyncTask)

问题出在哪

你的代码里future.get()是阻塞式调用,会把主线程死死卡住:

  • 虽然你用ExecutorService开了子线程跑HTTP请求,但调用future.get()时,主线程会一直等子线程把整个请求做完才继续干活。
  • ProgressDialog的显示是UI操作,得靠主线程的消息队列来渲染,主线程被卡住的时候,根本腾不出手处理Dialog的显示请求,只能等Search方法全执行完了才会去处理,所以对话框才会在搜索结束后才弹出来。
怎么改

得把阻塞主线程的future.get()去掉,改用异步回调的方式处理子线程的结果,同时保证UI操作(比如关Dialog)在主线程做。

修改后的代码示例

  1. 先定义一个回调接口,用来通知主线程搜索结果:
public interface OnSearchDoneListener {
    void onSuccess(Map<String, Object> result);
    void onFail(Exception e);
}
  1. 修改Search方法,去掉阻塞调用,换成异步执行逻辑:
public void Search(int idx, OnSearchDoneListener listener) {
    NetCheck nc = new NetCheck(this, false);
    if (!nc.checkNetwork()) {
        listener.onFail(new Exception("网络不可用"));
        return;
    }

    final NetTask nt = new NetTask();
    ExecutorService executor = Executors.newFixedThreadPool(
            Runtime.getRuntime().availableProcessors()
    );

    executor.submit(new Runnable() {
        @Override
        public void run() {
            try {
                Map<String, Object> result = nt.call();
                // 回到主线程通知搜索成功
                runOnUiThread(() -> {
                    listener.onSuccess(result);
                });
            } catch (Exception e) {
                // 回到主线程通知搜索失败
                runOnUiThread(() -> {
                    listener.onFail(e);
                });
            } finally {
                executor.shutdown();
            }
        }
    });
}
  1. 在点击事件里调用修改后的Search,正确处理Dialog的显示与关闭:
// 把ProgressDialog设为Activity成员变量,避免局部变量被提前回收
private ProgressDialog progressDialog;

@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.tool_btnRefresh:
            progressDialog = new ProgressDialog(MainActivity.this);
            progressDialog.setMessage("正在搜索...");
            progressDialog.setCancelable(true);
            progressDialog.setProgressStyle(android.R.style.Widget_ProgressBar_Horizontal);
            progressDialog.show(); // 现在能立刻弹出对话框了

            Search(0, new OnSearchDoneListener() {
                @Override
                public void onSuccess(Map<String, Object> result) {
                    // 处理搜索到的结果
                    List<Object> list = new ArrayList<>();
                    list.add(result);
                    // 关闭对话框
                    if (progressDialog != null && progressDialog.isShowing()) {
                        progressDialog.dismiss();
                    }
                }

                @Override
                public void onFail(Exception e) {
                    // 处理错误情况
                    if (progressDialog != null && progressDialog.isShowing()) {
                        progressDialog.dismiss();
                    }
                }
            });
            break;
    }
}

额外提醒

  • 绝对不能在主线程里执行耗时操作(包括网络请求、阻塞等待子线程),否则会导致UI卡顿甚至触发ANR(应用无响应)。
  • ProgressDialog在Android 8.0及以上版本已被废弃,推荐使用DialogFragment结合ProgressBar或Material Design组件替代,避免兼容性问题。
  • 记得在Activity销毁时检查并关闭Dialog,防止内存泄漏。

内容的提问来源于stack exchange,提问作者js u

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 01:25:24