Worker.setForegroundAsync在后台是如何工作的?

4

目前,在退出应用程序后,要在前台完成一个长时间运行的任务(以便操作系统不会将其杀死),我使用WorkManager实现了以下操作:

  1. 使用Worker调用ContextCompat.startForegroundService,启动一个IntentService
  2. Worker随即立刻返回Result.success()
  3. IntentServiceonHandleIntent方法中,它会在执行长时间运行的任务之前,调用startForeground方法。

以下是代码片段:

public class SyncWorker extends Worker {
    @NonNull
    @Override
    public Result doWork() {
        final Intent intent = new Intent(WeNoteApplication.instance(), SyncForegroundIntentService.class);

        ContextCompat.startForegroundService(
                WeNoteApplication.instance(),
                intent
        );

        return Result.success();
    }
}

public class SyncForegroundIntentService extends IntentService {
    private static final String TAG = "com.yocto.wenote.sync.SyncIntentService";

    public SyncForegroundIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {

        final Context context = WeNoteApplication.instance();

        NotificationCompat.Builder builder = new NotificationCompat.Builder(...

        startForeground(SYNC_FOREGROUND_INTENT_SERVICE_ID, builder.build());

        // Perform networking operation within foreground service.

        stopForeground(true);

我强烈打算迁移代码,使用 WorkManager 中的 setForegroundAsync。原因是,在某些罕见情况下,我会遇到以下崩溃:

Context.startForegroundService() did not then call Service.startForeground()

因此,我认为迁移到 setForegroundAsync 可以帮助消除这个问题。


然而,从 WorkForegroundUpdater 源代码 看,setForegroundAsync 的工作方式并不清楚。

以下是来自 https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-runningsetForegroundAsync 代码示例片段:

public class DownloadWorker extends Worker {
    public DownloadWorker(
        @NonNull Context context,
        @NonNull WorkerParameters parameters) {
            ...
    }

    @NonNull
    @Override
    public Result doWork() {
        ...

        // What happens behind the scene?!
        setForegroundAsync(createForegroundInfo(progress));

        // The long running task is still executed in Worker thread.
        download(inputUrl, outputFile);

        return Result.success();
    }

然而,目前不清楚这样的迁移是否能够达到相同的结果。以下是它们之间的区别。

迁移至 setForegroundAsync 之前

  1. 长时间运行的任务由 IntentService 的用户线程执行。
  2. 在长时间运行的任务完成之前,Worker 将立即返回。

迁移至 setForegroundAsync 之后

  1. 长时间运行的任务由 Worker 的用户线程执行。
  2. Worker 仅在长时间运行的任务完成执行后才会返回。

目前,通过我当前的实现,我将能够避免Excessive network usage (background)问题。但我不确定使用setForegroundAsync后,我是否仍能避免Excessive network usage (background)问题?

简而言之,有人知道 Worker.setForegroundAsync 在幕后如何工作吗?

1个回答

2
在幕后,当您在API >= 26上运行或在旧版Android上运行时,setForegroundAsync()会为您启动一个前台服务。这在参考文献中有所说明:

在幕后,WorkManager代表您管理和运行前台服务以执行此WorkRequest,并显示ForegroundInfo中提供的通知。

我认为相关源代码在Processor.java中。
谈到关键指标后台过度移动网络使用,考虑到使用WorkManager setForegroundAsync()也会将您的工作器移动到Android Oreo+上的前台服务,我不认为这种情况会发生变化。
有关如何测量此关键指标的其他信息,请参见Play Console指南

非常感谢您的输入!让我困惑的是,长时间运行的“download”函数仍在“DownloadWorker”的“doWork”函数中执行。它与新启动的前台服务有什么关系?我期望“download”将由新启动的前台服务执行。(类似于IntentService的onHandleIntent执行耗时函数) - Cheok Yan Cheng

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