Android 中的定時任務調度

在近期的應用開發中,異步執行任務是很流行的,並且這些任務常常在應用的生命週期以外運行,以下載數據或更新網絡資源。有些狀況下咱們還須要作一些並非立刻須要執行的工做。Android 提供了一些 API 來幫助咱們在應用中調度這些任務。html

選擇合適調度器能夠提高應用的性能而且延長電池使用時間。前端

Android M 還引入了 打盹模式(Doze mode) 來減小用戶在短時間內不使用設備時的電池消耗。java

Android 中可使用的調度器有如下幾種:react

  • Alarm Manager
  • Job Scheduler
  • GCM Network Manager
  • Firebase Job Dispatcher
  • Sync Adapter

Services 的問題

Services 容許應用在後臺執行長時間的操做, 但這一行爲是十分耗電的。android

當持續使用設備資源卻沒有有效任務在執行時,service 便更加有害了。當那些後臺服務在監聽不一樣系統廣播時(好比 CONNECTIVITY_CHANGE 或者 NEW_PICTURE 等),問題的嚴重性還會提高。 ios

在應用的生命週期以內調度任務

當應用正在運行時,若是咱們想在特定時間執行任務的話,推薦使用 Handler 結合 Timer 和 Thread,而不是使用 Alarm Manger, Job Scheduler 等。使用 Handler 更簡單高效。git

在應用的生命週期以外調度任務

Alarm Manager

AlarmManager 提供系統級的定時服務。正所以,也是一種在應用生命週期以外執行操做的方法。即便應用沒有運行,也能夠觸發事件或動做。AlarmManager 能夠在將來喚起服務。當達到預約時間時,觸發特定的 PendingIntent。github

註冊過的定時任務會在設備休眠時保留(而且能夠選擇是否喚醒設備),但在關機和重啓時會被清空。後端

「咱們應該只在執行特定時間的任務時使用 AlarmManager API。這並非一個用來粗暴檢查諸如設備空閒、網絡情況或充電狀況的方法。」api

用例:假設咱們想在一小時後執行任務或每隔一小時執行一次任務, AlarmManager 是完美選擇。但這 API 並不適合執行特定條件的任務,如網絡好或不充電時執行任務這種狀況。

Job Scheduler

這是全部提過的調度器中最主要的一個,它能夠高效地執行後臺任務。 JobScheduler API 是在 Android 5.0(API level 21) 引入的

該 API 能夠在資源充足時或知足條件時批量執行任務。建立任務時能夠定義執行的先決條件。當條件知足時,系統會在應用的 JobService 上執行任務。 JobScheduler 的執行也取決於系統的打盹模式和應用當前狀態。

批量執行的特性使得設備能夠更快地進入休眠,並擁有更長的休眠期,以此來延長電池使用時間。總而言之,這個 API 能夠用來執行任何對時間不敏感的計劃。

GCM Network Manager

GCM (Google Cloud Messaging) Network Manager 有着 JobScheduler 的所有特性,GCM Network Manager 也用在重複的或一次性的,不緊急的任務上來延長電量。

這個 API 是向下兼容的,支持 Android 5.0 (API level 21) 如下。從 API level 23 開始,GCM Network Manager 使用 Android 框架的 JobScheduler。GCM Network Manager 使用 Google Play 服務 內置的調度器,因此這個類 只會在安裝了 Google Play 服務 的設備上運行。

Google 強烈建議 GCM 的用戶升級到 FCM 並使用 Firebase Job Dispatcher 執行任務調度。

Firebase Job Dispatcher

Firebase JobDispatcher 也是一個後臺任務調度庫。該庫也被用來向下支持(低於 API level 21)而且支持全部近期 Android 設備(API level 9+)。

這個庫也能夠在沒有安裝 Google play 服務的設備,卻仍想調度任務的應用上使用。這時,庫內部的實現是 AlarmManager。若是設備上有 Google Play 服務,則會使用 Google Play 服務內置的調度器。

提示: 當 Google Play 服務不可用時,會使用 AlarmManager 來支持 API level <= 21

若是設備是 API level 21 的話,則使用 JobScheduler。這個庫的框架是相同的,因此沒有什麼功能改變。

Sync Adapter

Sync adapter 是被特別設計用來同步設備和雲端數據的。它的用途也只限定在這方面。同步能夠在雲端或客戶端數據有改變時觸發,也能夠經過時間差或設定每日一次。Android 系統會試圖執行批量同步來節省電量,沒法同步的將會被放到隊列中稍後執行。系統只在聯網時會嘗試執行同步。

無論什麼狀況,都建議使用 Google 提供的 JobScheduler、Firebase JobDispatcher、或 GCM Network Manager。

在 Android N (API level 24)中,SyncManager 在 JobScheduler (任務)的頂端。若是須要 SyncAdapter 提供的額外功能的話,建議只使用 SyncAdapter。

練習

咱們已經討論了一堆理論性的東西,下面來看看如何使用 Android job scheduler。

1. 創建 Job Service

創建 JobSchedulerService 並繼承 JobService 類,須要重寫下面兩個方法:onStartJob(JobParameters params)onStopJob(JobParameters params)

public class JobSchedulerService extends JobService {

@Override

public boolean onStartJob(JobParameters params) {

return false;

}

@Override

public boolean onStopJob(JobParameters params) {

return false;

}

}複製代碼

onStartJob(JobParameters params) 方法在 JobScheduler 決定執行任務時調用。JobService 在主線程工做,因此任何耗時操做都應該在另外的線程執行。onStopJob(JobParameters params) 在任務還沒執行完(調用 jobFinished(JobParameters, boolean) 以前),但系統決定中止執行時調用。

還須要在 AndroidManifest 中註冊 job service

  
 
   
   

 複製代碼

2. 建立 JobInfo 對象

創建 JobInfo 對象須要將 JobService 傳遞到 JobInfo.Builder() 中,以下所示。這個 job builder 容許設置不一樣選項來控制任務的執行。

ComponentName serviceName = new ComponentName(context, JobSchedulerService.class);

JobInfo jobInfo = new JobInfo.Builder(JOB_ID, serviceName)

.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)

.setRequiresDeviceIdle(true)

.setRequiresCharging(true)

.build();複製代碼

3. 調度任務

如今有了 JobInfo 和 JobService ,因此是時候來調度任務了。 用 JobInfo 調度任務時只須要執行以下代碼便可:

JobScheduler scheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);

int result = scheduler.schedule(jobInfo);

if (result == JobScheduler.RESULT_SUCCESS) {

Log.d(TAG, 「Job scheduled successfully!」);

}複製代碼

能夠在 GitHub 下載 JobSchedulerExample 的源碼

總結

當調度任務時,須要仔細考慮執行的時間和條件,以及出錯的後果。須要在應用性能和其餘電池之類的條件間取捨。

JobScheduler 容易實現,而且處理了大多數的複雜狀況。當使用 JobScheduler 時,即便系統重啓咱們的任務依舊能夠執行下去。此刻,JobScheduler 惟一的缺點就是它最低只在 api level 21 (Android 5.0) 上提供。

感謝閱讀。若是感受有用,還請輕點❤來推薦文章給更多人。

關注接下來的文章。有任何意見和建議請經過下面的渠道聯繫咱們: TwitterGoogle+LinkedIn

進入個人 博客 獲取更多有趣的開發話題。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOSReact前端後端產品設計 等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃

相關文章
相關標籤/搜索