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

Android Studio数独求解器ProgressBar显示异常问题求助

问题原因与解决方案

这个问题我之前也碰到过,核心是Android主线程的阻塞机制在搞鬼!

你现在的代码里,数独求解的耗时逻辑和UI操作都挤在主线程里:当你调用progBar.setVisibility(View.VISIBLE)后,紧接着就执行了耗时长的求解代码——主线程被这个计算任务占满了,根本没时间去刷新UI显示进度条。直到求解完成进入finally块,设置进度条隐藏的操作和之前的显示操作才一起被系统处理,结果就是进度条刚出现就被隐藏,看起来就像完全没显示过。

下面给你两种靠谱的解决方案,从传统到现代,你可以根据自己的项目情况选择:


方案1:用AsyncTask快速实现(适合入门或旧项目)

AsyncTask是Android专门为"后台任务+UI更新"场景设计的工具,它帮你封装了线程切换的逻辑,不用手动处理线程通信:

修改你的SudokuActivity.java代码如下:

private ProgressBar progBar = findViewById(R.id.progressBar);
// 加个标志位防止重复点击
private boolean isSolving = false;

public void SolveSudoku(View v) {
    if (isSolving) return;
    new SudokuSolverTask().execute();
}

// 定义一个AsyncTask子类处理求解任务
private class SudokuSolverTask extends AsyncTask<Void, Void, Boolean> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        isSolving = true;
        // 执行后台任务前,在主线程显示进度条
        progBar.setVisibility(View.VISIBLE);
    }

    @Override
    protected Boolean doInBackground(Void... voids) {
        // 耗时的数独求解逻辑放在这里,这个方法在子线程执行,不会阻塞UI
        try {
            // 把你原来的Solving logic代码挪到这里
            return true; // 返回true表示求解成功
        } catch (Exception ex) {
            // 原来的Error handling代码
            return false; // 返回false表示出错
        }
    }

    @Override
    protected void onPostExecute(Boolean success) {
        super.onPostExecute(success);
        isSolving = false;
        // 后台任务完成后,回到主线程隐藏进度条
        progBar.setVisibility(View.INVISIBLE);
        
        // 这里还可以根据success结果更新UI,比如显示求解结果或错误提示
        if (success) {
            // 处理求解成功的逻辑,比如更新数独格子
        } else {
            // 显示错误提示,比如Toast.makeText(...)
        }
    }
}

方案2:用Thread+Handler(更灵活的手动线程管理)

如果你不想用AsyncTask(比如它在Android 11后被标记为过时),可以手动开启子线程执行求解,再用Handler切回主线程更新UI:

private ProgressBar progBar = findViewById(R.id.progressBar);
private boolean isSolving = false;
// 获取主线程的Handler,用来切换回主线程更新UI
private Handler mainHandler = new Handler(Looper.getMainLooper());

public void SolveSudoku(View v) {
    if (isSolving) return;
    isSolving = true;
    
    // 先在主线程显示进度条
    progBar.setVisibility(View.VISIBLE);

    // 开启子线程执行耗时的求解逻辑
    new Thread(() -> {
        boolean success = false;
        try {
            // 原来的Solving logic代码
            success = true;
        } catch (Exception ex) {
            // 原来的Error handling代码
            success = false;
        } finally {
            // 任务完成后,通过Handler切换回主线程更新UI
            mainHandler.post(() -> {
                isSolving = false;
                progBar.setVisibility(View.INVISIBLE);
                
                // 处理结果UI
                if (success) {
                    // 求解成功的操作
                } else {
                    // 错误提示
                }
            });
        }
    }).start();
}

关键注意事项

  1. 绝对不要在子线程操作UI:所有修改UI的代码(比如设置ProgressBar的可见性)必须放在主线程执行,上面两个方案都严格遵守了这个规则。
  2. 防止重复触发:加isSolving标志位可以避免用户多次点击按钮导致多个求解线程同时运行,防止出现混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:54:33