觀察 worker 中繼進度

WorkManager 內建支援設定及觀察工作站的中間進度。如果工作站在應用程式於前景運作時執行,該資訊也可透過會回傳 WorkInfo 的 LiveData API 向使用者顯示這項資訊。

ListenableWorker 現在支援 setProgressAsync() API,可使其保留中階進度。這些 API 可讓開發人員設定使用者介面可察看的中階進度。系統會以 Data 類型表示進度,其為屬性的可序列化容器 (類似於 input 和 output,並且受到相同的限制)。

只有在 ListenableWorker 執行期間,才能查看及更新進度資訊。嘗試在 ListenableWorker 上設定進度,且執行作業完成後就會被忽略。

您也可以使用 getWorkInfoBy…() 或 getWorkInfoBy…LiveData() 方式察看進度資訊。這些方法會回傳 WorkInfo 的執行個體,而新的 getProgress() 方法會回傳 Data。

更新進度

針對使用 ListenableWorker 或 Worker 的 Java 開發人員,setProgressAsync() API 會回傳 ListenableFuture<Void>;更新進度並非同步,因為更新程序需要將進度資訊儲存在資料庫中。在 Kotlin 中,您可以使用 CoroutineWorker 物件的 setProgress() 擴充功能函式來更新進度資訊。

此範例顯示 ProgressWorker。Worker 會在開始時將進度設為 0,完成時則將進度值更新為 100。

Kotlin

import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.Data
import androidx.work.WorkerParameters
import kotlinx.coroutines.delay

class ProgressWorker(context: Context, parameters: WorkerParameters) :
    CoroutineWorker(context, parameters) {

    companion object {
        const val Progress = "Progress"
        private const val delayDuration = 1L
    }

    override suspend fun doWork(): Result {
        val firstUpdate = workDataOf(Progress to 0)
        val lastUpdate = workDataOf(Progress to 100)
        setProgress(firstUpdate)
        delay(delayDuration)
        setProgress(lastUpdate)
        return Result.success()
    }
}

Java

import android.content.Context;
import androidx.annotation.NonNull;
import androidx.work.Data;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

public class ProgressWorker extends Worker {

    private static final String PROGRESS = "PROGRESS";
    private static final long DELAY = 1000L;

    public ProgressWorker(
        @NonNull Context context,
        @NonNull WorkerParameters parameters) {
        super(context, parameters);
        // Set initial progress to 0
        setProgressAsync(new Data.Builder().putInt(PROGRESS, 0).build());
    }

    @NonNull
    @Override
    public Result doWork() {
        try {
            // Doing work.
            Thread.sleep(DELAY);
        } catch (InterruptedException exception) {
            // ... handle exception
        }
        // Set progress to 100 after you are done doing your work.
        setProgressAsync(new Data.Builder().putInt(PROGRESS, 100).build());
        return Result.success();
    }
}

查看進度

如要觀察進度資訊,請使用 getWorkInfoById 方法,並取得 WorkInfo 的參考資料。

以下是使用 getWorkInfoByIdFlow (適用於 Kotlin) 和 getWorkInfoByIdLiveData (適用於 Java) 的範例。

Kotlin

WorkManager.getInstance(applicationContext)
      // requestId is the WorkRequest id
      .getWorkInfoByIdFlow(requestId)
      .collect { workInfo: WorkInfo? ->
          if (workInfo != null) {
              val progress = workInfo.progress
              val value = progress.getInt("Progress", 0)
              // Do something with progress information
          }
      }

Java

WorkManager.getInstance(getApplicationContext())
     // requestId is the WorkRequest id
     .getWorkInfoByIdLiveData(requestId)
     .observe(lifecycleOwner, new Observer<WorkInfo>() {
             @Override
             public void onChanged(@Nullable WorkInfo workInfo) {
                 if (workInfo != null) {
                     Data progress = workInfo.getProgress();
                     int value = progress.getInt(PROGRESS, 0)
                     // Do something with progress
             }
      }
});

觀察停止原因狀態

如要偵錯 Worker 停止的原因,可以呼叫 WorkInfo.getStopReason() 記錄停止原因:

Kotlin

workManager.getWorkInfoByIdFlow(syncWorker.id)
  .collect { workInfo ->
      if (workInfo != null) {
        val stopReason = workInfo.stopReason
        logStopReason(syncWorker.id, stopReason)
      }
  }

Java

  workManager.getWorkInfoByIdLiveData(syncWorker.id)
    .observe(getViewLifecycleOwner(), workInfo -> {
        if (workInfo != null) {
          int stopReason = workInfo.getStopReason();
          logStopReason(syncWorker.id, workInfo.getStopReason());
        }
  });

如要進一步瞭解 Worker 物件的生命週期和狀態,請參閱「作業狀態」。