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

Android Service:使用 Timer 定時重複執行任務

     編輯:程式設計綜合問答

問題背景

在 Service 中使用 while(true) 迴圈配合 Thread.sleep() 會導致 ANR(應用程式無回應)且無法正確控制生命週期。

錯誤代碼

public class RepService extends Service {
    @Override public IBinder onBind(Intent intent) { return null; }
    
    // 錯誤:while(true) 會阻塞主執行緒,導致 ANR
    while(true) {
        Thread timer = new Thread() {
            public void run() {
                try { sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }
            }
        };
        timer.start();
    }
}

正確方案:Timer + TimerTask

public class RepService extends Service {
    private Timer timer;
    
    @Override
    public void onCreate() {
        super.onCreate();
        timer = new Timer();
        // 立即執行,每 5 分鐘重複一次 (300000 毫秒)
        timer.schedule(new TimerTask() {
            @Override public void run() {
                // 執行週期性任務
                doPeriodicWork();
            }
        }, 0, 5 * 60 * 1000); // 5 分鐘
    }
    
    private void doPeriodicWork() {
        // 如果需要更新 UI,必須切回主執行緒
        new Handler(Looper.getMainLooper()).post(() -> updateUI());
    }
    
    @Override
    public void onDestroy() {
        timer.cancel(); // 釋放資源
        super.onDestroy();
    }
    
    @Override public IBinder onBind(Intent intent) { return null; }
}

進階方案:AlarmManager + BroadcastReceiver

更省電、系統級排程,適合精確或非精確週期任務:

// 在 Service 或 Application 啟動時設定
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, PeriodicReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);

// 每 5 分鐘觸發一次 (非精確,省電)
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, 
    System.currentTimeMillis(), 5 * 60 * 1000, pi);

// 接收器
public class PeriodicReceiver extends BroadcastReceiver {
    @Override public void onReceive(Context context, Intent intent) {
        // 執行任務,建議啟動 IntentService 或 JobIntentService
    }
}

現代最佳實踐:WorkManager

Android Jetpack WorkManager 是目前推薦的延遲任務框架:

PeriodicWorkRequest work = new PeriodicWorkRequest.Builder(
    MyWorker.class, 15, TimeUnit.MINUTES) // 最小間隔 15 分鐘
    .build();
WorkManager.getInstance(context).enqueue(work);

// Worker 類別
public class MyWorker extends CoroutineWorker {
    public MyWorker(@NonNull Context context, @NonNull WorkerParameters params) {
        super(context, params);
    }
    
    @NonNull @Override public Result doWork() {
        // 背景執行緒執行任務
        return Result.success();
    }
}

選擇指南

方案適用場景優點缺點
Timer應用內短週期、非精確簡單、輕量進程死掉即停止
AlarmManager系統級排程、需喚醒裝置可跨進程、精確控制API 19+ 非精確、Doze 模式限制
WorkManager可延遲、需保證執行、支援約束生命週期感知、跨版本相容最小間隔 15 分鐘
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved