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

runOnUiThread报错致App崩溃,求修复非UI线程无障碍内容变更问题

问题修复方案

错误原因分析

  1. UI线程被阻塞:refresh方法本身运行在UI线程(按钮点击回调默认在UI线程),你在runOnUiThread的Runnable里调用了Thread.sleep(5000),这会直接阻塞UI线程,导致应用无响应甚至崩溃。
  2. 不必要的UI线程调度:循环中连续向UI线程post12个任务,每个任务都阻塞5秒,完全占用了UI线程,无法处理其他界面事件。
  3. 非UI操作占用UI线程:内存状态计算属于非UI操作,放在UI线程会额外消耗UI线程资源。

修复后的代码

Java代码

package com.tools.cpuusage;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;

public class MainActivity2 extends AppCompatActivity {
    private ProgressBar[] progressBars;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        
        // 用数组存储ProgressBar,简化后续操作
        progressBars = new ProgressBar[]{
                findViewById(R.id.progressBar1),
                findViewById(R.id.progressBar2),
                findViewById(R.id.progressBar3),
                findViewById(R.id.progressBar4),
                findViewById(R.id.progressBar5),
                findViewById(R.id.progressBar6),
                findViewById(R.id.progressBar7),
                findViewById(R.id.progressBar8),
                findViewById(R.id.progressBar9),
                findViewById(R.id.progressBar10),
                findViewById(R.id.progressBar11),
                findViewById(R.id.progressBar12)
        };
    }

    public void refresh(View view) {
        // 启动后台线程处理循环和延迟,避免阻塞UI
        new Thread(() -> {
            int accuracy = 100;
            
            for (int c = 0; c < 12; c++) {
                int finalC = c;
                // 计算内存状态,放在后台线程
                int memory = (int) ((double) accuracy * 
                        ((double)(Runtime.getRuntime().freeMemory() / (1024 * 1024)) / 
                        (double)(Runtime.getRuntime().totalMemory() / (1024 * 1024))));
                
                // 仅更新UI时切换到UI线程
                runOnUiThread(() -> {
                    if (finalC == 0) {
                        progressBars[finalC].setProgress(0);
                    } else if (finalC <= 3) {
                        progressBars[finalC].setProgress(78);
                    } else {
                        progressBars[finalC].setProgress(memory);
                    }
                });
                
                // 在后台线程执行延迟,不阻塞UI
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException ignore) {}
            }
        }).start();
    }
}

关键优化点

  • 后台线程处理耗时逻辑:将循环、延迟、内存计算都放在后台线程,仅在更新ProgressBar时切换到UI线程。
  • 数组存储控件引用:替换大量if-else判断,简化代码逻辑。
  • 解除UI线程阻塞:将Thread.sleep移到后台线程,保证UI线程始终能响应用户操作。

额外建议

  • 如果需要定期刷新内存状态,推荐使用Handler或协程(Kotlin)实现定时任务,比手动管理线程更稳定。
  • 可以给ProgressBar设置最大进度(setMax(100)),确保进度值在合理范围内。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 09:15:54