從 GCMNetworkManager 遷移至 WorkManager

本文說明如何遷移應用程式,以便使用 WorkManager 用戶端程式庫 (而非 GCMNetworkManager 程式庫) 來執行背景作業。如果應用程式要安排背景工作,建議的方式是使用 WorkManager。此外,你也能納入 WorkManager GCM 程式庫,讓 WorkManager 在搭載 API 級別 22 以下版本的 Android 裝置上執行時,能夠使用 GCM 排定工作。

遷移至 WorkManager

如果你的應用程式目前使用 GCMNetworkManager 執行背景作業,請按照下列步驟遷移至 WorkManager。

在以下步驟中,我們假設你一開始使用的是以下 GCMNetworkManager 程式碼,該程式碼定義了你的工作並加以排程:

Kotlin

val myTask = OneoffTask.Builder()
    // setService() says what class does the work
    .setService(MyUploadService::class.java)
    // Don't run the task unless device is charging
    .setRequiresCharging(true)
    // Run the task between 5 & 15 minutes from now
    .setExecutionWindow(5 * DateUtil.MINUTE_IN_SECONDS,
            15 * DateUtil.MINUTE_IN_SECONDS)
    // Define a unique tag for the task
    .setTag("test-upload")
    // ...finally, build the task and assign its value to myTask
    .build()
GcmNetworkManager.getInstance(this).schedule(myTask)

Java

// In GcmNetworkManager, this call defines the task and its
// runtime constraints:
OneoffTask myTask = new OneoffTask.Builder()
    // setService() says what class does the work
    .setService(MyUploadService.class)
    // Don't run the task unless device is charging
    .setRequiresCharging(true)
    // Run the task between 5 & 15 minutes from now
    .setExecutionWindow(
        5 * DateUtil.MINUTE_IN_SECONDS,
        15 * DateUtil.MINUTE_IN_SECONDS)
    // Define a unique tag for the task
    .setTag("test-upload")
    // ...finally, build the task and assign its value to myTask
    .build();
GcmNetworkManager.getInstance(this).schedule(myTask);

在這個範例中,我們假設 MyUploadService 定義了實際上傳作業:

Kotlin

class MyUploadService : GcmTaskService() {
    fun onRunTask(params: TaskParams): Int {
        // Do some upload work
        return GcmNetworkManager.RESULT_SUCCESS
    }
}

Java

class MyUploadService extends GcmTaskService {
    @Override
    public int onRunTask(TaskParams params) {
        // Do some upload work
        return GcmNetworkManager.RESULT_SUCCESS;
    }
}

包含 WorkManager 程式庫

如要使用 WorkManager 類別,你必須將 WorkManager 程式庫新增至建構依附元件。你還必須新增 WorkManager GCM 程式庫;這樣一來,當應用程式在不支援 JobScheduler 的裝置 (即執行 API 級別 22 以下版本的裝置) 上執行時,WorkManager 就能使用 GCM 處理工作)。如需新增程式庫的完整詳細資料,請參閱開始使用 WorkManager

修改資訊清單

實作 GCMNetworkManager 後,應按照 GcmNetworkManager 參考說明文件所述,將 GcmTaskService 執行個體加入你的應用程式資訊清單。GcmTaskService 會查看傳入的工作,並委派給工作處理常式。WorkManager 會管理對工作站的工作委派作業,因此不再需要類別來執行此工作;只要將 GcmTaskService 從資訊清單中移除即可。

定義工作站

你的 GCMNetworkManager 實作會定義 OneoffTaskRecurringTask,表明需要完成的工作。按照定義工作要求所述,你必須將工作重新編寫為 Worker

GCMNetworkManager 程式碼範例定義了 myTask 工作。WorkManager 對應看起來會像這樣:

Kotlin

class UploadWorker(context: Context, params: WorkerParameters)
                        : Worker(context, params) {
    override fun doWork() : Result {
        // Do the upload operation ...
        myUploadOperation()

        // Indicate whether the task finished successfully with the Result
        return Result.success()
    }
}

Java

public class UploadWorker extends Worker {

    public UploadWorker(
        @NonNull Context context,
        @NonNull WorkerParameters params) {
        super(context, params);
    }

    @Override
    public Result doWork() {
      // Do the upload operation ...

      myUploadOperation()

      // Indicate whether the task finished successfully with the Result
      return Result.success()
    }
}

GCM 工作與 Worker 之間有一些差異:

  • GCM 使用 TaskParams 物件將參數傳遞至工作。WorkManager 會使用輸入資料。如要在 WorkRequest 設定這項資料,你可參閱 WorkManager 說明文件,瞭解如何定義工作的輸入/輸出。在這兩種情況下,你都可以傳送鍵/值組合,指定工作所需的任何可持續參數。
  • GcmTaskService 信號會傳回 GcmNetworkManager.RESULT_SUCCESS 等旗標,指出結果為成功或失敗。WorkManager Worker 使用 ListenableWorker.Result.success()ListenableWorker.Result 方法指出其結果,並傳回該方法的傳回值。
  • 如先前所述,你不必在定義 Worker 時設定限制條件或標記;而是在下一個步驟建立 WorkRequest 時設定。

安排工作要求

定義 Worker 會指定你需要的「結果」。如要指定工作的完成時間,你必須定義 WorkRequest

  1. 建立 OneTimeWorkRequestPeriodicWorkRequest,並設定任何想要的限制條件來指定工作執行時間,以及任何有助辨別工作的標記。
  2. 將要求傳遞至 WorkManager.enqueue(),以將工作排入佇列等待執行。

例如,上一節說明如何將 OneoffTask 轉換為對等的 Worker。不過,這個 Worker 並不包含 OneoffTask 物件的執行限制和標記。因此,我們是在建立 WorkRequest 時設下限制和工作 ID。我們也會指定,除非有網路連線,否則工作不得執行。根據預設,GCM 管理員需要網路連線,因為 GCMNetworkManager 預設為需要網路連線,但除非你特別新增限制,否則 WorkManager 不需要網路連線。定義 WorkRequest 後,我們會使用 WorkManager 將其排入佇列。

Kotlin

val uploadConstraints = Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresCharging(true).build()

val uploadTask = OneTimeWorkRequestBuilder<UploadWorker>()
    .setConstraints(uploadConstraints)
    .build()
WorkManager.getInstance().enqueue(uploadTask)

Java

Constraints uploadConstraints = new Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresCharging(true)
    .build();

OneTimeWorkRequest uploadTask =
        new OneTimeWorkRequest.Builder(UploadWorker.class)
  .setConstraints(uploadConstraints)
  .build();
WorkManager.getInstance().enqueue(uploadTask);

API 對應

本節說明部分 GCMNetworkManager 功能與限制如何對應至 WorkManager 對等項目。

限制對應

GCMNetworkManager 可讓你設定工作執行時間的幾個限制。在多數情況下,都會有明確的 WorkManager 限制對等項目。本節會列出這些對等項目。

在工作的 Builder 物件中呼叫適當的方法,以設定 GCMNetworkManager 工作的限制;舉例來說,你可以呼叫 Task.Builder.setRequiredNetwork() 來設定網路需求。

在 WorkManager 中,建立 Constraints.Builder 物件並呼叫該物件的方法,藉此設定限制 (例如 Constraints.Builder.setRequiredNetworkType())),然後使用 Builder 建立限制物件,並將該物件附加至工作要求。詳情請參閱定義工作要求

GCMNetworkManager 限制 WorkManager 對應 附註
setPersisted() (非必要) 每部裝置重新啟動後都會保留所有 WorkManager 工作
setRequiredNetwork() setRequiredNetworkType() 根據預設,GCMNetworkManager 需要網路存取權。根據預設,WorkManager 不需要網路存取權。如果你的工作需要存取網路,你必須使用 setRequiredNetworkType(CONNECTED),或設定更具體的網路類型。
setRequiresCharging()

其他對應

除了限制外,你還可以將其他設定套用到 GCMNetworkManager 工作。本節列出將這些設定套用至 WorkManager 工作的對應方法。

標記

所有 GCMNetworkManager 工作都必須包含標記字串,而你必須透過呼叫 Builder 的 setTag() 方法來設定這些字串。WorkManager 工作是由 WorkManager 自動產生的不重複 ID 所代表;你可以呼叫 WorkRequest.getId() 來取得這個 ID。此外,工作要求也「可以」具有一或多個標記。如要為 WorkManager 工作設定標記,請先呼叫 WorkRequest.Builder.addTag() 方法,再使用 Builder 建立 WorkRequest

在 GCMNetworkManager 中,你可以呼叫 setUpdateCurrent() 來指定工作是否應以相同的標記取代任何現有的工作。 對應的 WorkManager 方法是透過呼叫 enqueueUniqueWork()enqueueUniquePeriodicWork() 將工作排入佇列。如果使用上述方法,你可以為工作指定專屬名稱,並指定 WorkManager 如何處理已使用該名稱的待處理工作。詳情請參閱處理不重複的工作

工作參數

你可以呼叫 Task.Builder.setExtras() 並傳遞包含參數的 Bundle,以將參數傳遞至 GCMNetworkManager 工作。WorkManager 可讓你將 Data 物件傳遞至 WorkManager 工作,其中包含參數做為鍵/值組合。詳情請參閱指派輸入資料一文。