如何观察 Android WorkManager 工作器

5

我的当前Android应用采用了

archWorkerRuntimeVersion = '2.3.0-beta02'

api "androidx.work:work-runtime:$archWorkerRuntimeVersion"
api "androidx.work:work-runtime-ktx:$archWorkerRuntimeVersion"

处理后台任务。

当工作程序正在运行时,我会显示一个工具栏进度旋转器,向用户表示应用程序正在“忙碌”状态。

我的应用程序由多个活动组成,我使用 Android JetPack ViewModels 来管理工作者。

我按以下方式启动工作:

val myWorkRequest: OneTimeWorkRequest =
    OneTimeWorkRequest.Builder(MyWorker::class.java)
        .addTag(WORK_IN_PROGRESS_TAG + "${UUID.randomUUID()}").build()

    WorkManager.getInstance(applicationContext)
        .beginUniqueWork(
            UNIQUE_WORK_NAME,
            ExistingWorkPolicy.KEEP,
            myWorkRequest
        )
        .enqueue()

我有一个定义如下的观察者:

private val observer = Observer<WorkInfo> { workInfo ->

    when(workInfo.state) {
        WorkInfo.State.RUNNING -> Log.e("OBSERVING", "${UUID.randomUUID()} :: show Progress Spinner")
        WorkInfo.State.ENQUEUED -> Log.e("OBSERVING", "${UUID.randomUUID()} :: show Progress Spinner")
        WorkInfo.State.SUCCEEDED -> Log.e("OBSERVING", "${UUID.randomUUID()} :: stop showing Progress Spinner")
        WorkInfo.State.FAILED -> Log.e("OBSERVING", "${UUID.randomUUID()} :: stop showing Progress Spinner")
        WorkInfo.State.BLOCKED -> Log.e("OBSERVING", "${UUID.randomUUID()} :: show Progress Spinner")
        WorkInfo.State.CANCELLED -> Log.e("OBSERVING", "${UUID.randomUUID()} :: stop showing Progress Spinner")
    }

}

我将如下观察工作流程: -
 WorkManager.getInstance(applicationContext)
            .getWorkInfoByIdLiveData(myWorkRequest.id)
            .observe(lifeCycleOwner, observer)

并在我的视图模型中记住当前的workId

class MyViewModel : ViewModel() {

    private var currentWorkInfoId: UUID? = null


  fun startWorkTags(lifeCycleOwner: LifecycleOwner, applicationContext: Context) {

        val myWorkRequest: OneTimeWorkRequest =
    OneTimeWorkRequest.Builder(MyWorker::class.java)
        .addTag(WORK_IN_PROGRESS_TAG + "${UUID.randomUUID()}").build()

    WorkManager.getInstance(applicationContext)
        .beginUniqueWork(
            UNIQUE_WORK_NAME,
            ExistingWorkPolicy.KEEP,
            myWorkRequest
        )
        .enqueue()

        currentWorkInfoId = myWorkRequest.id
   }
}

我有如下问题:
1). 我正在使用 ExistingWorkPolicy.KEEP,需要知道是否已经有后台工作在运行,以便我不会记错工作 ID。目前,我无条件地记住最后一个尝试执行 enqueue() 的工作 ID。有没有办法检测到 ExistingWorkPolicy.KEEP 没有启动新工作?
2). 当用户退出我的应用程序时,我将当前工作 ID 存储在我的 viewModel 中,导致失去了这个 ID。当用户重新进入我的应用程序时,我该如何发现自己有活动的 worker?
对于问题 2)。我已尝试使用

 WorkManager.getInstance(applicationContext)
            .getWorkInfosForUniqueWorkLiveData(UNIQUE_WORK_NAME)
            .observe(lifeCycleOwner, observerUnique)

然而,这种方法“看到”了所有先前的工人执行情况,我该如何识别最新的工人实例?
1个回答

2
考虑到您只想在 Worker 运行时显示进度旋转器,您可以实现一个更简单的解决方案,其中您的观察者只检查是否有一个处于非最终状态的 Worker。
observe(this, listOfWorkInfo -> {
    // If there are no matching work info, do nothing
    if (listOfWorkInfo == null || listOfWorkInfo.isEmpty()) {
        return;
    }

    boolean showProgress = false;
    for (WorkInfo workInfo : listOfWorkInfo) {
        if (!(workInfo.getState().isFinished())) {
            showProgress = true;
        }
    }

    if (showProgress) {
        showSpinner();
    } else {
        hideSpinner();
    }

}

你可以使用getWorkInfosForUniqueWorkLiveData()获取WorkInfos列表。
另一种解决方案是使用WorkManager v2.3.0中引入的新Progress API,这已经在你正在使用的版本中了。
具体思路是,在worker启动时(在构造函数中)立即发布进度更新:
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, 1).build());
    }

    @NonNull
    @Override
    public Result doWork() {
        try {
            // Doing work.
            Thread.sleep(DELAY);
        } catch (InterruptedException exception) {
            // ... handle exception
        }
        return Result.success();
    }
}

您可以使用workInfo.getProgress()在观察器中检索进度。在这种情况下的好处在于,只有在worker正在运行时才能获得进度信息。
您仍然可以从UniqueWorkName请求所有WorkInfos,但是只有当worker正在运行时才会有进度信息。
当worker处于最终状态时,WorkManager将负责删除进度信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接