Android 的 WorkerManager 何时停止 Worker?

Pao*_*one 8 android android-workmanager

我们有一个 Android 应用程序,使用 WorkManager 来处理后台同步工作。我们的同步工作者是这样的:

public class SyncWorker extends Worker {

    [...]

    @NonNull
    @Override
    public Result doWork() {

        if (canNotRetry(getRunAttemptCount())) {
            // This could seem unreachable, consider removing... or not... because if stopped by the
            // system, the work might be retried by design
            CBlogger.INSTANCE.log([...]);
            return Result.success();
        }

        boolean syncOk = false;

        //Sync
        try (Realm realm = Realm.getDefaultInstance()) {

            // Doing sync related ops & network calls
            // checking this.isStopped() between operations to quit
            // sync activity when worker has to be stopped

            syncOk = true;
        } catch (Throwable throwable) {
            CBlogger.INSTANCE.log([...]);
        }

        // On error, continue with following code to avoid any logic in catch
        // This method must NOT throw any unhandled exception to avoid unique work to be marked as failed
        try {

            if (syncOk) {
                return Result.success();
            }

            if (canNotRetry(getRunAttemptCount() + 1)) {
                CBlogger.INSTANCE.log([...]);
                return Result.success();
            } else {
                CBlogger.INSTANCE.log([...]);
                return Result.retry();
            }
        } catch (Throwable e) {
            CBlogger.INSTANCE.log([...]);
            return Result.success();
        }
    }

    private boolean canNotRetry(int tryNumber) {
        // Check if the work has been retry too many times
        if (tryNumber > MAX_SYNC_RETRY_COUNT) {
            CBlogger.INSTANCE.log([...]);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void onStopped() {
        CBlogger.INSTANCE.log([...]);
    }
}
Run Code Online (Sandbox Code Playgroud)

该工作由一个助手类的专用方法调度:

    public static void scheduleWorker(Context context, String syncPolicy, ExistingWorkPolicy existingWorkingPolicy){

        Constraints constraints = new Constraints.Builder()
                .setRequiresCharging(false)
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .build();

        Data.Builder data = new Data.Builder();
        data.putString(context.getResources().getString(R.string.sync_worker_policy), syncPolicy);

        Log.d(TAG, "Scheduling one-time sync request");
        logger.info("Scheduling one-time sync request");
        OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder
                (SyncWorker.class)
                .setInputData(data.build())
                .setConstraints(constraints)
                .setBackoffCriteria(
                        BackoffPolicy.LINEAR,
                        OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
                        TimeUnit.MILLISECONDS)
                .build();

        WorkManager.getInstance(context).enqueueUniqueWork("OneTimeSyncWorker", existingWorkingPolicy, oneTimeWorkRequest);
    }
Run Code Online (Sandbox Code Playgroud)

当用户单击“同步”按钮或由另一个计划每 20' 运行一次并以这种方式调用帮助程序的函数时调用它:

SyncWorkerManager.scheduleWorker(context, context.getResources().getString(R.string.sync_worker_policy_full), ExistingWorkPolicy.KEEP);
Run Code Online (Sandbox Code Playgroud)

以便新的同步只有在尚未等待或运行时才会排队。请注意,同步工作策略强制要求连接网络。

这个策略onStopped()总体上效果很好,但有时我们会在日志中发现SyncWorker 启动后几秒钟(大约 10 英寸)调用Worker 的方法。

知道我们从不以编程方式为外部停止特定的 Worker,我们只WorkManager.getInstance(context).cancelAllWork();在注销过程中或新登录之前调用(也调度 del 定期 Worker),系统何时可以决定停止 Worker 并调用其onStopped()方法?

我知道这可能发生在:

  • 不再满足约束(网络连接断开)
  • Worker 运行超过 10' 由 JobScheduler 实现施加的限制(我们的场景在 Android 9 设备上测试)
  • 新的独特工作以相同的名称和 REPLACE 策略入队(我们从不在我们的应用程序中为 SyncWorker 使用此策略,仅用于 PeriodicSyncWorker)
  • 由于此错误导致的虚假调用(我们使用“androidx.work:work-runtime:2.2.0”)

是否有任何其他情况会导致 Worker's 被停止?就像是:

  • 打瞌睡模式
  • 应用备用桶
  • 应用后台限制(设置 --> 应用 --> 我的应用 --> 电池 --> 允许后台)
  • 应用电池优化(设置 --> 应用 --> 我的应用 --> 电池 --> 电池优化)

谢谢

key*_*fer 0

有多种原因Worker可以停止 a。您可以明确要求取消它,否则 WorkManager 可能会因此处记录的各种原因而停止它。