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

Android Handler實現固定周期任務的正確姿勢

     編輯:程式設計綜合問答

postDelayed必須在run()內部遞歸調用才能形成循環

使用Handler.postDelayed(Runnable, delayMillis)實現周期性任務時,常見錯誤是只在外部調用一次,導致任務僅執行一次。關鍵在於在run()方法結尾處再次postDelayed。

錯誤代碼:僅執行一次

mRunnable = new Runnable() {
    @Override public void run() {
        if (count == 0) { setImage(); count = 1; }
        else { weather = ...; count = 0; }
        // 缺少遞歸postDelayed,任務結束後不再調度
    }
};
mHandler = new Handler();
mHandler.postDelayed(mRunnable, 3000); // 只執行一次

正確代碼:run內部遞歸調度

mHandler = new Handler();
mRunnable = new Runnable() {
    @Override
    public void run() {
        // 1. 執行具體任務邏輯
        if (count == 0) {
            setImage();
            count = 1;
        } else {
            weather = mContentResolver.getType(mUri);
            setWeather(weather);
            count = 0;
        }
        // 2. 關鍵:在run結尾重新postDelayed,形成循環
        mHandler.postDelayed(this, 3000); // this指向當前Runnable實例
    }
};

// 3. 啟動:直接調用run()或postDelayed均可
mRunnable.run(); // 立即執行第一次
// 或 mHandler.postDelayed(mRunnable, 3000); // 延遲3秒執行第一次

關鍵點解析

  1. 遞歸調度:mHandler.postDelayed(this, 3000)在run()末尾調用,確保每次執行完重新排隊。
  2. 使用this:傳遞當前Runnable實例,避免創建新對象。
  3. 停止機制:需提供stop()方法調用mHandler.removeCallbacks(mRunnable),防止內存洩漏與Activity銷毀後繼續執行。

完整可控的周期任務封裝類


public class PeriodicTask {
    private final Handler handler = new Handler(Looper.getMainLooper());
    private final Runnable runnable;
    private final long intervalMillis;
    private boolean running = false;

    public PeriodicTask(long intervalMillis, Runnable task) {
        this.intervalMillis = intervalMillis;
        this.runnable = () -> {
            task.run();
            if (running) handler.postDelayed(runnable, intervalMillis);
        };
    }

    public void start() {
        if (!running) {
            running = true;
            handler.post(runnable); // 立即執行首次
        }
    }

    public void stop() {
        running = false;
        handler.removeCallbacks(runnable);
    }
}

// 使用
PeriodicTask task = new PeriodicTask(3000, () -> {
    // 任務邏輯
});
task.start();
// onDestroy()中 task.stop();

替代方案對比

方案優點缺點
Handler + postDelayed輕量、主線程安全、易控制需手動管理生命周期
ScheduledExecutorService標準API、支持固定頻率/延遲非主線程,更新UI需runOnUiThread
Timer/TimerTask簡單異常會終止所有任務、不推薦新代碼
RxJava interval響應式、鏈式操作、自動生命周期綁定引入依賴、學習曲線
Kotlin Coroutines結構化並發、自動取消需Kotlin環境
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved