Задержка отката WorkManager не работает на некоторых устройствах - PullRequest
0 голосов
/ 15 января 2019

Я хочу запустить Worker, который выполняет какую-то задачу, и в случае ошибки пытается снова после некоторой задержки с экспоненциальной стратегией отсрочки.

Вот упрощенно Worker для краткости:

class TestWorker(
    context: Context,
    workerParameters: WorkerParameters
) : Worker(
    context,
    workerParameters
) {
    override fun doWork(): Result {
        Log.d("DEBUG", "Attempt $runAttemptCount")
        return Result.retry()
    }
}

И вот как я планирую это Worker:

class MainActivity : AppCompatActivity() {

private val TAG = "WORKER_TAG"
private val BACKOFF_DELAY_SECONDS = 60L

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val workManager = WorkManager.getInstance()
        workManager.cancelAllWork()
        val workRequest = OneTimeWorkRequest.Builder(TestWorker::class.java)
            .setConstraints(
                Constraints
                    .Builder()
                    .setRequiredNetworkType(NetworkType.CONNECTED)
                    .build()
            )
            .setBackoffCriteria(
                BackoffPolicy.EXPONENTIAL,
                BACKOFF_DELAY_SECONDS,
                TimeUnit.SECONDS
            )
            .addTag(TAG)
            .build()

        workManager.enqueue(workRequest)
    }
}

Отлично работает на большинстве устройств, однако я наблюдаю странное поведение на некоторых устройствах.

Я ожидаю, что попытка 2 будет выполнена через 1 минуту, но на Samsung J1, 6.0.1 я вижу следующий журнал:

01-15 12:39:57.438 28396-28435/test.ru.workerissue D/DEBUG: Attempt 0
01-15 12:39:58.349 28396-28439/test.ru.workerissue D/DEBUG: Attempt 1
01-15 12:39:58.389 28396-28440/test.ru.workerissue D/DEBUG: Attempt 2
01-15 12:40:59.669 28396-28435/test.ru.workerissue D/DEBUG: Attempt 3
01-15 12:40:59.719 28396-28439/test.ru.workerissue D/DEBUG: Attempt 4

Как видите, задержка между всеми попытками, кроме 2 и 3, составляет около 1 секунды.

Если я запускаю один и тот же код на Nexus 6X, 8.1, я наблюдаю две попытки при запуске одновременно, и тогда все работает как положено:

2019-01-15 13:01:06.610 28806-28841/test.ru.workerissue D/DEBUG: Attempt 0
2019-01-15 13:01:06.658 28806-28842/test.ru.workerissue D/DEBUG: Attempt 1
2019-01-15 13:02:06.747 28806-28975/test.ru.workerissue D/DEBUG: Attempt 2
2019-01-15 13:04:06.876 28806-29024/test.ru.workerissue D/DEBUG: Attempt 3

Кроме того, я протестировал это на нескольких других устройствах: Samsung Galaxy J3 - 8.0, Google Pixel XL - 8.1, Samsung Galaxy J1 - 5.1.1. Работает должным образом на всех этих устройствах.

Версия WorkManager равна 1.0.0-beta01

В чем может быть причина такого несоответствия? Можно ли это исправить?

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Я создал проблему, и она должна быть исправлена ​​в следующей версии WorkManager: https://issuetracker.google.com/issues/122881597

0 голосов
/ 15 января 2019

Изменить: WorkManager 1.0.0-beta02 выпущен с исправлением ошибки, которая, кажется, связана с проблемой, с которой вы

Исправлен пограничный случай, когда периодическая работа могла выполняться более одного раза за интервал на устройствах под управлением Android 6.0 (уровень API 23).

Оригинальный ответ:
Вы должны стараться не ставить в очередь WorkRequest при каждом запуске приложения. WorkManager позаботится о возобновлении работы для вас, и вам не нужно это делать. Для получения дополнительной информации о WorkManager и о том, что он может для вас сделать, вам следует обратиться к этой серии блогов . Также есть видео с выступления саммита разработчиков Android "Работа с WorkManager" , в котором это объясняется.

Если вам нужно ставить новые работы в очередь каждый раз, когда ваше приложение запускается, я советую ставить его в качестве уникального работника, используя политику REPLACE:

private val TAG = "WORKER_TAG"
private val BACKOFF_DELAY_SECONDS = 60L

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val workManager = WorkManager.getInstance()
        val workRequest = OneTimeWorkRequest.Builder(TestWorker::class.java)
            .setConstraints(
                Constraints
                    .Builder()
                    .setRequiredNetworkType(NetworkType.CONNECTED)
                    .build()
            )
            .setBackoffCriteria(
                BackoffPolicy.EXPONENTIAL,
                BACKOFF_DELAY_SECONDS,
                TimeUnit.SECONDS
            )
            .addTag(TAG)
            .build()

        // The first parameter is a unique string that identifies the work, I'm using the TAG here.
        workManager.enqueueUniqueWork(TAG, ExistingWorkPolicy.REPLACE, workRequest)
    }
}

Я вижу, что вы используете cancelAllWork() методы. Это опасный метод, и вы не предпринимаете никаких действий, чтобы остановить работника во время его работы (например, вызвать isStopped).

Это может быть источником дополнительного журнала, который вы получаете на устройстве nexus.

...