b1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
class T1 extends Thread {
int i = 0;
public void run() {
while (true) {
for (int j = 0; j < 60; j++) {
doit();
}
i = 0;
}
}
public void doit() {
try { sleep(1000); } catch (Exception e) {}
tt3.setText("" + i); // ❌ 致命錯誤:子線程更新 UI
i++;
}
}
new T1().start();
}
});
View.setText() 會拋出 CalledFromWrongThreadException// 在 Activity 中定義 Handler
private Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
tt3.setText(String.valueOf(msg.arg1));
}
}
};
// 子線程中發送消息
public void doit() {
try { Thread.sleep(1000); } catch (Exception e) {}
Message msg = mHandler.obtainMessage(1, i, 0);
mHandler.sendMessage(msg);
i++;
}
runOnUiThread(new Runnable() {
@Override
public void run() {
tt3.setText(String.valueOf(i));
}
});
tt3.post(new Runnable() {
@Override
public void run() {
tt3.setText(String.valueOf(i));
}
});
b1.setOnClickListener(v -> {
new Thread(() -> {
int i = 0;
while (true) {
for (int j = 0; j < 60; j++) {
try { Thread.sleep(1000); } catch (InterruptedException e) { return; }
final int current = i;
runOnUiThread(() -> tt3.setText(String.valueOf(current)));
i++;
}
i = 0;
}
}).start();
});
Handler 而非 runOnUiThread 避免內存洩漏(靜態內部類 + WeakReference)CountDownTimer 替代手動睡眠循環withContext(Dispatchers.Main) { tt3.text = i.toString() }InterruptedException 支持線程取消Android 視圖操作只能在主線程執行,跨線程更新 UI 必須通過消息隊列(Handler/Looper)分發到主線程。