首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java 下載進度條異步更新:線程分離與參數傳遞

     編輯:程式設計綜合問答

問題現象

  • 下載開始時進度條與「是否安裝」彈窗同時彈出(應下載完成後才彈窗)。
  • 進度條跳變:30% → 0 → 再增長,永不到 100%。

根本原因

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();

關鍵點

  1. 線程分離:耗時 I/O 放後台線程,UI 更新拋回事件分發線程(EDT/JavaFX Application Thread/Android UI Thread)。
  2. 進度計算:基於 Content-Length 與已寫入字節數實時計算,避免緩衝區導致跳變。
  3. 狀態機:下載中/完成/失敗三態,完成後才觸發彈窗邏輯。
  4. 取消支持:提供 volatile boolean cancelled 標誌,下載循環檢查並清理臨時文件。

常用框架簡化

  • Swing: SwingWorker 自動處理線程切換與進度綁定。
  • JavaFX: Task + ProgressBar.progressProperty().bind(task.progressProperty())。
  • Android: AsyncTask (已棄用) / Coroutine + Flow / DownloadManager 系統服務。

徹底分離下載邏輯與 UI 更新,進度條才會絲滑流暢、彈窗才會適時出現。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved