UI 線程被阻塞 / 邏輯耦合:下載邏輯與 UI 更新在同一線程,或未正確同步進度數據,導致界面假死、進度回調亂序。
// 1. 下載線程(生產者)
new Thread(() -> {
try (InputStream in = url.openStream();
FileOutputStream out = new FileOutputStream(file)) {
byte[] buf = new byte[8192];
int len, total = 0;
long fileSize = connection.getContentLengthLong();
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
total += len;
final int progress = (int) (total * 100.0 / fileSize);
// 2. 通過 Handler/Platform.runLater 發送到 UI 線程
SwingUtilities.invokeLater(() -> progressBar.setValue(progress));
}
// 3. 下載完成,UI 線程彈窗
SwingUtilities.invokeLater(() -> {
int opt = JOptionPane.showConfirmDialog(null, "安裝?");
if (opt == JOptionPane.YES_OPTION) install(file);
});
} catch (Exception e) { e.printStackTrace(); }
}).start();
Content-Length 與已寫入字節數實時計算,避免緩衝區導致跳變。volatile boolean cancelled 標誌,下載循環檢查並清理臨時文件。SwingWorker 自動處理線程切換與進度綁定。Task + ProgressBar.progressProperty().bind(task.progressProperty())。AsyncTask (已棄用) / Coroutine + Flow / DownloadManager 系統服務。徹底分離下載邏輯與 UI 更新,進度條才會絲滑流暢、彈窗才會適時出現。