WorkManager - 如何按顺序执行作业

15

我有一个监听FCM通知的服务。当收到这样的通知时,我使用WorkManager运行一个作业。

当同时接收到多个通知时,如何确保一次只执行一个作业?这些作业应该按顺序执行。在这种情况下,我想发送短信,这些短信不能同时发送。(请注意,在发送短信之前和之后,我还会做其他事情,比如http请求,这就是为什么我决定创建一个作业而不是直接从服务中发送短信的原因。)

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    public void onMessageReceived(RemoteMessage remoteMessage) {
        //...
        OneTimeWorkRequest sendSmsWorker = new OneTimeWorkRequest.Builder(SendSmsWorker.class).build();
        WorkManager.getInstance().enqueue(sendSmsWorker);
        //...
    }
}

我已查看了WorkManager文档中的高级部分;它提到了Chained sequences,但这些序列必须显式地链接在一起(beginWith/then/then/...)。

3个回答

24

你需要使用相同的组名将任务创建为OneTimeWorkRequest,并将它们作为带有APPEND唯一工作项进行排队。 这将使所有的任务都被追加到同一个链上并依次执行。

请注意,您应该始终返回Result.SUCCESS,或者最多返回Result.RETRY。返回Result.FAILURE将取消所有已排队的作业。 如果您需要知道作业是否失败,则可以在worker setOutputData中设置自定义标志来处理此类情况,根据需要进行操作。

final String JOB_GROUP_NAME = "your_jobs_group_name";

......

OneTimeWorkRequest request = new OneTimeWorkRequest.Builder(YOUR_WORK.class)
    .setInputData(YOUR_WORK_DATA_BUILDER.build())
    .build();

final WorkManager workManager = WorkManager.getInstance();
WorkContinuation work = workManager.beginUniqueWork(JOB_GROUP_NAME, ExistingWorkPolicy.APPEND, request);
work.enqueue();

1
注意:在这种情况下,您无法停止组中的一个作业。除非您在某个地方存储了该特定工作的UUID。 - Andrew
1
我尝试使用ExistingWorkPolicy.APPEND,但这只能在某个程度上起作用。如果您必须将27个工作程序加入队列,则它们在某些时候将保持运行状态并永远无法完成。我在此处的问题跟踪器中打开了一个问题:https://issuetracker.google.com/issues/155370056 - Etienne Lawlor
1
通过始终返回“Result.SUCCESS”或“Result.RETRY”的解决方法,您如何取消正在运行的作业而不取消整个链? - xatok

0

如果你在执行Workers时不想受到返回结果为Result.SUCCESS以外的限制,还有一种方法是继承ListenableWorker而不是Worker,这样就可以顺序执行Workers而不会中断链条。

如果你查看Worker实现代码,它们使用了WorkManager的后台执行器来运行所有的Worker实例。你也可以定义自己的执行器,使用单个线程:

// Define your executor here
private static final Executor sExecutor = Executors.newSingleThreadExecutor();

@Override
    public final @NonNull ListenableFuture<Result> startWork() {
        mFuture = SettableFuture.create();
        sSerialExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    Result result = doWork();
                    mFuture.set(result);
                } catch (Throwable throwable) {
                    mFuture.setException(throwable);
                }

            }
        });
        return mFuture;
    }

请注意,您将需要使用Guava的SettableFuture

0

在Work Manager中有一个概念,即链接,我们可以将工作人员安排为任意数量的订单。

假设有一些连续的任务,我们必须

  1. 创建一些数据
  2. 缓存数据
  3. 上传该数据

现在,为了实现这一点,我们可以链接它们以便按顺序运行。

WorkManager.getInstance(myContext)
   .beginWith(createDataWork) //This is going enqueue first
   .then(cacheWork)  // enqueue after returning success from create worker
   .then(uploadWork)// enqueue after returning success from cache worker
   .enqueue() 

每个then都会返回一个new WorkerContinuation()实例。

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