首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Android 定時器 Timer 與 Handler 協作機制完整指南

     編輯:Java 相關知識

前言

Android 開發中常需執行週期性任務(輪詢、心跳、同步)或延遲任務。Timer 提供背景執行緒定時排程,但不能直接更新 UI;Handler 綁定主執行緒 Looper,可安全更新 UI。兩者結合是經典模式。本文系統整理 Timer、Handler、Runnable 的單獨與組合用法。

1. Timer 基本用法

// 成員變數
private Timer timer = new Timer();
private static final int INTERVAL_MS = 5000;

// 初始化
timer.schedule(new TimerTask() {
    @Override public void run() {
        // 背景執行緒執行,不可直接操作 View
        doBackgroundWork();
    }
}, INTERVAL_MS, INTERVAL_MS); // 首次延遲、週期皆 5 秒

2. Timer + Handler 更新 UI


private Handler uiHandler = new Handler(Looper.getMainLooper()) {
    @Override public void handleMessage(Message msg) {
        if (msg.what == 1) {
            textView.setText("資料已更新:" + System.currentTimeMillis());
        }
    }
};

private TimerTask createUITask() {
    return new TimerTask() {
        @Override public void run() {
            // 背景工作
            String data = fetchData();
            // 送訊息給主執行緒
            Message msg = uiHandler.obtainMessage(1, data);
            uiHandler.sendMessage(msg);
        }
    };
}

3. Handler + Runnable 延遲/週期執行(無 Timer)

輕量級週期任務可僅用 Handler 實現,避免額外執行緒開銷:


private Handler handler = new Handler(Looper.getMainLooper());
private Runnable periodicTask = new Runnable() {
    @Override public void run() {
        updateUI();
        handler.postDelayed(this, 2000); // 2 秒後再次執行
    }
};

// 啟動
handler.post(periodicTask);
// 停止
handler.removeCallbacks(periodicTask);

4. 實戰場景:網路連線狀態機


enum State { FREE, CONNECTING, CONNECTED, LOGGED_IN, IN_ROOM }

private State state = State.FREE;
private Timer timer = new Timer();
private Handler handler = new Handler(Looper.getMainLooper());

private void startStateMachine() {
    timer.schedule(new TimerTask() {
        @Override public void run() {
            switch (state) {
                case FREE:
                    connect("10.58.1.59", 8906); break;
                case CONNECTED:
                    login("user", "pwd"); break;
                case LOGGED_IN:
                    enterRoom(1); break;
                case IN_ROOM:
                    handler.sendEmptyMessage(1); // 通知 UI 開啟視訊
                    break;
            }
        }
    }, 0, 3000); // 每 3 秒檢查一次
}

handler = new Handler(Looper.getMainLooper()) {
    @Override public void handleMessage(Message msg) {
        if (msg.what == 1) startVideoPreview();
    }
};

5. 記憶體洩漏與生命週期管理

  • Timer:Activity.onDestroy() 呼叫 timer.cancel(),並設 timer = null。
  • Handler:靜態內部類 + WeakReference<Activity>,或使用 Handler(Looper.getMainLooper()) 並在 onDestroy removeCallbacksAndMessages(null)。
  • 避免匿名內部類隱性持有外部類引用導致洩漏。

對照表

方案優點缺點適用場景
Timer + Handler背景執行緒不阻塞 UI,精確週期兩個物件管理較繁瑣需在背景做耗時運算再更新 UI
Handler + Runnable單一物件、程式碼簡潔任務在主執行緒執行,耗時操作會卡頓輕量級 UI 週期更新、延遲執行
ScheduledExecutorService功能最強、支援取消、固定延遲/固定頻率API 較複雜高併發、精確排程、需取消未來任務
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved