简体   繁体   中英

Why does Jetpack WorkManager call doWork() repeatedly?

Problem Description

When using WorkManager to perform the only task, after an error occurs in doWork() and the handling exception is Result.failure(), doWork() will be called again.

I tried to troubleshoot the error through the log file, and I found that the setComponentEnabled(context, SystemJobService.class, true); of androidx.work.impl.Schedulers#createBestAvailableBackgroundScheduler was called twice. WorkManagerImpl is a singleton object and will not be called twice. So I am very confused.

Log

01-15 15:25:01.198  7797  7797 D WM-PackageManagerHelper: androidx.work.impl.background.systemjob.SystemJobService enabled
01-15 15:25:01.198  7797  7797 D WM-Schedulers: Created SystemJobScheduler and enabled SystemJobService
01-15 15:25:01.208  7797  7847 D WM-ForceStopRunnable: Performing cleanup operations.
01-15 15:25:01.303  7797  7851 D WM-PackageManagerHelper: androidx.work.impl.background.systemalarm.RescheduleReceiver enabled
01-15 15:25:01.319  7797  7851 D WM-SystemJobScheduler: Scheduling work ID b278a34c-aeeb-4c88-8f29-71b9c23e0954 Job ID 68
01-15 15:25:01.327  7797  7851 D WM-GreedyScheduler: Starting work for b278a34c-aeeb-4c88-8f29-71b9c23e0954
01-15 15:25:01.334  7797  7858 D WM-Processor: Processor: processing b278a34c-aeeb-4c88-8f29-71b9c23e0954
01-15 15:25:02.742  7797  7797 D WM-WorkerWrapper: Starting work for my_package.service.StatisticsService
01-15 15:25:02.822  7797  7847 D WM-WorkerWrapper: my_package.service.StatisticsService returned a Failure {mOutputData=Data {}} result.
01-15 15:25:02.829  7797  7847 I WM-WorkerWrapper: Worker result FAILURE for Work [ id=b278a34c-aeeb-4c88-8f29-71b9c23e0954, tags={ my_package.service.StatisticsService } ]
01-15 15:25:02.842  7797  7847 D WM-PackageManagerHelper: androidx.work.impl.background.systemalarm.RescheduleReceiver disabled
01-15 15:25:02.847  7797  7797 D WM-SystemJobService: onStartJob for b278a34c-aeeb-4c88-8f29-71b9c23e0954
01-15 15:25:02.847  7797  7847 D WM-GreedyScheduler: Cancelling work ID b278a34c-aeeb-4c88-8f29-71b9c23e0954
01-15 15:25:02.862  7797  7851 D WM-Processor: Work b278a34c-aeeb-4c88-8f29-71b9c23e0954 is already enqueued for processing
01-15 15:25:02.868  7797  7851 D WM-Processor: Processor stopping background work b278a34c-aeeb-4c88-8f29-71b9c23e0954
01-15 15:25:02.869  7797  7851 D WM-WorkerWrapper: Work interrupted for Work [ id=b278a34c-aeeb-4c88-8f29-71b9c23e0954, tags={ my_package.service.StatisticsService } ]
01-15 15:25:02.883  7797  7851 D WM-PackageManagerHelper: androidx.work.impl.background.systemalarm.RescheduleReceiver disabled
01-15 15:25:02.884  7797  7851 D WM-WorkerWrapper: WorkSpec {WorkSpec: b278a34c-aeeb-4c88-8f29-71b9c23e0954} is already done. Not interrupting.
01-15 15:25:02.884  7797  7851 D WM-Processor: WorkerWrapper interrupted for b278a34c-aeeb-4c88-8f29-71b9c23e0954
01-15 15:25:02.884  7797  7851 D WM-StopWorkRunnable: StopWorkRunnable for b278a34c-aeeb-4c88-8f29-71b9c23e0954; Processor.stopWork = true
01-15 15:25:02.899  7797  7797 D WM-Processor: Processor b278a34c-aeeb-4c88-8f29-71b9c23e0954 executed; reschedule = false
01-15 15:25:02.900  7797  7797 D WM-SystemJobService: b278a34c-aeeb-4c88-8f29-71b9c23e0954 executed on JobScheduler
01-15 15:25:02.900  7797  7797 D WM-SystemJobService: onStopJob for b278a34c-aeeb-4c88-8f29-71b9c23e0954
01-15 15:25:02.903  7797  7847 D WM-Processor: Processor stopping background work b278a34c-aeeb-4c88-8f29-71b9c23e0954
01-15 15:25:02.903  7797  7847 D WM-Processor: WorkerWrapper could not be found for b278a34c-aeeb-4c88-8f29-71b9c23e0954
01-15 15:25:02.904  7797  7847 D WM-StopWorkRunnable: StopWorkRunnable for b278a34c-aeeb-4c88-8f29-71b9c23e0954; Processor.stopWork = false

// Here doWork() is repeated once.

01-15 15:25:04.511  7923  7923 D WM-PackageManagerHelper: androidx.work.impl.background.systemjob.SystemJobService enabled
01-15 15:25:04.511  7923  7923 D WM-Schedulers: Created SystemJobScheduler and enabled SystemJobService
01-15 15:25:04.519  7923  7985 D WM-ForceStopRunnable: Performing cleanup operations.
01-15 15:25:04.600  7923  7989 D WM-PackageManagerHelper: androidx.work.impl.background.systemalarm.RescheduleReceiver enabled
01-15 15:25:04.616  7923  7989 D WM-SystemJobScheduler: Scheduling work ID 07bddcf0-33c3-43c5-ad2b-0dcb1f200e18 Job ID 69
01-15 15:25:04.624  7923  7989 I WM-GreedyScheduler: Ignoring schedule request in non-main process
01-15 15:25:04.633  7797  7797 D WM-SystemJobService: onStartJob for 07bddcf0-33c3-43c5-ad2b-0dcb1f200e18
01-15 15:25:04.634  7797  7851 D WM-Processor: Processor: processing 07bddcf0-33c3-43c5-ad2b-0dcb1f200e18
01-15 15:25:04.650  7797  7797 D WM-WorkerWrapper: Starting work for my_package.service.StatisticsService
01-15 15:25:04.697  7797  7847 D WM-WorkerWrapper: my_package.service.StatisticsService returned a Failure {mOutputData=Data {}} result.
01-15 15:25:04.700  7797  7847 I WM-WorkerWrapper: Worker result FAILURE for Work [ id=07bddcf0-33c3-43c5-ad2b-0dcb1f200e18, tags={ my_package.service.StatisticsService } ]
01-15 15:25:04.704  7797  7847 D WM-PackageManagerHelper: androidx.work.impl.background.systemalarm.RescheduleReceiver disabled
01-15 15:25:04.704  7797  7797 D WM-Processor: Processor 07bddcf0-33c3-43c5-ad2b-0dcb1f200e18 executed; reschedule = false
01-15 15:25:04.705  7797  7797 D WM-SystemJobService: 07bddcf0-33c3-43c5-ad2b-0dcb1f200e18 executed on JobScheduler
01-15 15:25:04.713  7797  7847 D WM-GreedyScheduler: Cancelling work ID 07bddcf0-33c3-43c5-ad2b-0dcb1f200e18
01-15 15:25:04.718  7797  7847 D WM-Processor: Processor stopping background work 07bddcf0-33c3-43c5-ad2b-0dcb1f200e18
01-15 15:25:04.719  7797  7847 D WM-Processor: WorkerWrapper could not be found for 07bddcf0-33c3-43c5-ad2b-0dcb1f200e18
01-15 15:25:04.719  7797  7847 D WM-StopWorkRunnable: StopWorkRunnable for 07bddcf0-33c3-43c5-ad2b-0dcb1f200e18; Processor.stopWork = false


Scenes

I need to perform a task that is only executed once every time I open the app to upload my statistics, and if there is no network, cache it.

My environment

jetpack workmanager 2.4.0

My code

Application.java

// Start a background only task.
StatisticsService.startService(getApplicationContext());

StatisticsService.java

public static void startService(Context context) {
    OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(StatisticsService.class);
    ...
    Data.Builder data = new Data.Builder();
    data.putBoolean(EXTRA_IS_FIRST, isFirstOpenApp);
    builder.setInputData(data.build());
    WorkManager.getInstance(context).enqueueUniqueWork("StatisticsService", ExistingWorkPolicy.APPEND_OR_REPLACE, builder.build());
}


@NonNull
@Override
public Result doWork() {
    log.info("doWork:" + hashCode());
    boolean isSuccessful = false;
    try {
        Data inputData = getInputData();
        boolean isFirstOpenApp = inputData.getBoolean(EXTRA_IS_FIRST, true);
        isSuccessful = uploadStatisticsInfo(isFirstOpenApp);
        if (isSuccessful) {
            return Result.success();
        } else {
            return Result.failure();
        }
    } catch (Exception e) {
        log.severe(ThrowableUtils.getFullStackTrace(e));
        return Result.failure();
    }
}

private boolean uploadStatisticsInfo(boolean isFirstOpenApp) {
    // Synchronously determine whether the network is available.
    // If the network is unavailable, an exception will be thrown.
    boolean available = NetworkUtils.isAvailable();
    if (!available) {
        AppStatisticsBean.cacheOneMap(isFirstOpenApp);
        return false;
    }
    // Upload statistics
    ...

    if (success){
        return true;
    } else {
        return false;
    }
}

You are enqueuing your WorkRequest as a unique work with a ExistingWorkPolicy.APPEND_OR_REPLACE policy. This means that if there is already another request pending, the new one is appended to the existing one creating a chain of work.
The replace part is only used if the previous work has failed.

Creating a chain of work, once a worker is executed correctly, the next one in the chain is going to be executed. This is explained in WorkManager's documentation .

An alternative is to use the ExistingWorkPolicy.KEEP policy so that only one WorkRequest is going to be enqueued.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM