ワーカーの中間進捗状況の監視

WorkManager には、ワーカーの中間進捗状況の設定および監視に関する組み込みのサポートがあります。アプリがフォアグラウンドで実行されているときにワーカーが実行されていた場合、この情報も、WorkInfoLiveData を返す API を使用して、ユーザーに表示できます。

ListenableWorker が中間進捗状況を保持可能な setProgressAsync() API をサポートするようになりました。デベロッパーはこの API を使用して、UI で監視可能な中間進捗状況を設定できます。進捗状況は、プロパティのシリアル化可能なコンテナ(input および output に似ており、同じ制限を受ける)である Data 型で表されます。

進捗状況情報を監視および更新できるのは、ListenableWorker が実行されている間だけです。ListenableWorker の実行完了後にその進捗状況を設定しようとしても無視されます。

進捗状況情報は、getWorkInfoBy…() または getWorkInfoBy…LiveData() のいずれかのメソッドを使用して監視することも可能です。これらのメソッドは、Data を返す新しい getProgress() メソッドを持つ WorkInfo のインスタンスを返します。

更新の進行状況

Java で ListenableWorker または Worker を使用している場合、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 への参照を取得します。

以下に、Kotlin で getWorkInfoByIdFlow、Java で getWorkInfoByIdLiveData を使用する例を示します。

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 オブジェクトのライフサイクルと状態について詳しくは、処理の状態をご覧ください。