Android的WorkerManager何时停止工作程序?

时间:2019-12-04 11:57:19

标签: android android-workmanager

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

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([...]);
    }
}

通过助手类的专用方法安排工作:

    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);
    }

,当用户单击“同步”按钮时,或由计划每20秒运行一次并以这种方式调用帮助程序功能的其他工作人员调用时,会调用

SyncWorkerManager.scheduleWorker(context, context.getResources().getString(R.string.sync_worker_policy_full), ExistingWorkPolicy.KEEP);

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

此策略完全奏效,但有时我们在日志中发现在SyncWorker启动后几秒钟(约10英寸)内调用了Worker的onStopped()方法。

众所周知,我们从不以编程方式停止外部的特定Worker,而仅在注销过程中或在新登录之前(也安排了del定期Worker)调用WorkManager.getInstance(context).cancelAllWork();,系统何时才能决定停止工人并调用其onStopped()方法?

我知道它可能在以下情况下发生:

  • 不再满足约束条件(网络连接断开)
  • Worker运行JobScheduler实施设置的限制超过10'(我们的方案在Android 9设备上经过测试)
  • 使用相同名称和REPLACE策略排队的新的独特作品(我们从未在SyncWorker的应用程序中使用此策略,仅在PeriodicSyncWorker中使用此策略)
  • 由于this bug而导致的虚假呼叫(我们使用“ androidx.work:work-runtime:2.2.0”)

是否还有其他条件可能导致工人被阻止?像这样:

  • 打ze模式
  • 应用程序备用存储桶
  • 应用背景限制(设置->应用->我的应用->电池->允许背景)
  • 应用程序电池优化(设置->应用程序->我的应用程序->电池->电池优化)

谢谢

1 个答案:

答案 0 :(得分:0)

有多种原因可以停止 Worker。您可以明确要求取消它,否则 WorkManager 可能会出于各种原因(documented here)停止它。