#java #android #worker
Вопрос:
Краткое описание:
В настоящее время я работаю в Android Studio с OneTimeWorkRequest()
. Чего я хочу добиться, так это создать фонового рабочего, который запускается и повторяется «почти» в определенное время, например, каждый час (09:00, 10:00 и т. Д.). Это не должно быть точно, но не должно слишком сильно изменяться после длительного времени работы.
Я уже знаю, что рабочий запускается как минимум каждые 15 минут из-за ограничений Android (например, механизм экономии заряда батареи и так далее). Мне не нужно, чтобы работник работал точно в заданное время, но, по крайней мере, почти в заданное время! Вот почему я использовал OneTimeWorkRequest()
вместо PeriodicWorkRequest()
этого, потому что мне нужна была возможность изменения настройки интервала для рабочего, поскольку в документации упоминается, что PeriodicWorkRequest()
это приведет к временной задержке от одного выполнения к другому.
Что я сделал:
Я создал пользовательский рабочий класс и использовал OneTimeWorkRequest()
его в своем MainActivity
для создания BackgroundWorker. Я установил время setInitialDelay()
работы рабочего на 20 минут для целей тестирования. Каждый раз, когда работник делал doWork()
это, он создает еще OneTimeWorkRequest()
одного в конце выполнения, поэтому в данный момент времени создается цепочка работников. Работник встает в очередь с enqueueUniqueWork()
помощью метода из WorkerManager.getInstance(context)
, и вычисляется интервал.
Проблема:
Каждый раз, когда я закрываю процесс приложения и снова открываю приложение, работник выполняется напрямую. Также, когда я перечисляю всех работников, созданных указанным тегом, в нем перечисляется много работников. Мне кажется, что моя логика создала слишком много рабочих, не закрыв старых, или она создает несколько? Все же я думал enqueueUniqueWork()
, что он заменит или создаст только уникального/единственного работника с данным тегом… Кроме того WorkManager.getInstance(this).cancelAllWorkByTag(TAG)
, функция не закрывает (далее в этом посте) перечисленного работника!
Прямо сейчас для меня важно не то, как создать выполнение рабочего в данный момент времени, а как создать согласованную рабочую цепочку, при OneTimeWorkRequest()
этом не создавайте «перегрузку рабочего», если это возможно. И все же я открыт для альтернативных решений.
Итак, еще раз:
- Почему рабочий выполняется после закрытия процесса и открытия приложения?
- Почему в списке так много работников?
- Создает ли моя логика одну единственную рабочую цепочку или несколько?
- Является ли моя логика вообще последовательной/применимой таким образом?
- Почему рабочий не закрывает использование
.cancelAllWorkByTag(TAG)
?
Код:
// MainActivity.java:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
// For testing purpose used...
ListScheduledWorker(TAG);
WorkManager.getInstance(this).cancelAllWorkByTag(TAG);
ListScheduledWorker(TAG);
// ...until here.
CreateOneTimeWorker();
...
}
private void CreateOneTimeWorker(){
long timeValue = 20;
TimeUnit timeUnit = TimeUnit.MINUTES;
String workerTag = MhdExpirationPushNotification.class.getSimpleName();
OneTimeWorkRequest worker = new OneTimeWorkRequest.Builder(CustomPeriodicallyWorker.class)
.setInitialDelay(timeValue, timeUnit)
.addTag(workerTag)
.setConstraints(Constraints.NONE)
.build();
WorkManager.getInstance(this).enqueueUniqueWork(workerTag, ExistingWorkPolicy.KEEP, worker);
}
// CustomPeriodicallyWorker.java:
public Result doWork(){
Log.v(TAG, "Work is in progress");
try {
CustomDateFormatter currentDateTime = new CustomDateFormatter();
CustomDateFormatter targetDateTime = new CustomDateFormatter();
targetDateTime.AddMinutes(20);
long timeDifference = targetDateTime.GetDateTime().getTime() - currentDateTime.GetDateTime().getTime();
OneTimeWorkRequest worker = new OneTimeWorkRequest.Builder(CustomPeriodicallyWorker.class)
.setInitialDelay(timeDifference, TimeUnit.MILLISECONDS)
.addTag(TAG)
.build();
WorkManager.getInstance(context).enqueueUniqueWork(TAG, ExistingWorkPolicy.REPLACE, worker);
} catch (Exception e) {
e.printStackTrace();
}
Log.v(TAG, "Work finished");;
return Result.success();
}
// The function in MainActivity.java
that lists all scheduled worker:
private boolean ListScheduledWorker(String tag) {
WorkManager instance = WorkManager.getInstance(this);
ListenableFuture<List<WorkInfo>> statuses = instance.getWorkInfosByTag(tag);
try {
boolean running = false;
List<WorkInfo> workInfoList = statuses.get();
for (WorkInfo workInfo : workInfoList) {
Log.i(TAG, "Scheduled Worker running with ID: " workInfo.getId());
WorkInfo.State state = workInfo.getState();
running = state == WorkInfo.State.RUNNING | state == WorkInfo.State.ENQUEUED;
}
return running;
} catch (ExecutionException e) {
e.printStackTrace();
return false;
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
// The ListScheduledWorker(String tag)
prints me this out:
I/TAG: Scheduled Worker running with ID: 27bb31ed-5984-434f-a6ca-08b50462b3df
Scheduled Worker running with ID: 2d6abbb1-3a55-4652-83ca-60617631e0ab
Scheduled Worker running with ID: 3e89851d-7e0b-410d-86b8-e664a4d710f0
Scheduled Worker running with ID: 430e77b2-5fb8-4596-acd5-51e35a6a538b
Scheduled Worker running with ID: 73b57443-8195-4c55-a24d-bd643b88e13c
Scheduled Worker running with ID: 74c8a44b-2a9a-4448-b3d5-e2c085be3d06
Scheduled Worker running with ID: 75deabd3-08e8-403a-b9d7-6c23f114a908
Scheduled Worker running with ID: 89ec6239-e215-4ea1-a7bc-fcaa8b63065c
Scheduled Worker running with ID: 9363038e-be74-4a83-9d1f-eeeda35ebbfa
Scheduled Worker running with ID: 9a09806f-f0cf-43c1-a4f6-1f10448904f4
Scheduled Worker running with ID: c6686c56-fd8a-4866-8eb1-5124654b6cb7
Scheduled Worker running with ID: d3343328-db8f-4c8d-8055-a1acfc9d1c5c
Scheduled Worker running with ID: dea9272f-6770-45f0-ba66-2c845e156d7b
Scheduled Worker running with ID: eb4c111c-97c5-46c3-ba5c-ceefe652398c
Scheduled Worker running with ID: fc71f8dc-1785-43cd-9a44-1fe4e913ca6e
Scheduled Worker running with ID: fca1bcea-97d9-4066-8b5a-8b5496ffed1e
..and the list grows everytime when I rebuild/restart the App in Android Studio or on my physical device.