我目前在 Android Studio 中与
OneTimeWorkRequest()
一起工作。我想要实现的是创建一个后台工作者,它在特定时间运行并重复“几乎”,比如每小时(09:00、10:00 等)。它不一定是准确的,但在长时间运行后不应变化太大。
我已经知道,由于 android 的限制(比如省电机制等),worker 至少每 15 分钟运行一次。我不需要工作人员在给定时间准确运行,但至少几乎在目标时间附近运行!这就是为什么我使用
OneTimeWorkRequest()
而不是 PeriodicWorkRequest()
的原因,因为我需要在为工作人员设置间隔时有变化的可能性,因为文档提到 PeriodicWorkRequest()
会增加从一次执行到另一次执行的时间延迟。
我创建了一个自定义 Worker-Class 并在我的
OneTimeWorkRequest()
中使用了 MainActivity
来创建 BackgroundWorker。我已将工人的setInitialDelay()
设置为20分钟以进行测试。每当 worker 执行 doWork()
时,它都会在执行结束时创建另一个 OneTimeWorkRequest()
,以便在给定时间创建一个 worker 链。工作人员使用enqueueUniqueWork()
中的WorkerManager.getInstance(context)
方法排队,并计算间隔。
每次关闭App的进程再打开App,Worker直接执行。此外,当我列出由指定标签创建的所有工人时,它会列出许多工人。在我看来,我的逻辑在没有关闭旧工人的情况下创造了太多工人,还是创造了多个工人?然而我认为
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();
}
//
MainActivity.java
中的函数,列出所有调度的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;
}
}
//
ListScheduledWorker(String tag)
打印出来:
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
..每次当我在 Android Studio 或我的物理设备上重建/重启应用程序时,列表都会增长。
我会尽力回答其中一些问题。
为什么worker在关闭进程打开后执行 应用程序?
不确定,但您可以在应用程序启动时取消所有带有该标签的独特工作,这将阻止它自动执行。
为什么列出这么多工人?
WorkManager
将 WorkInfo
s 保存在它的内部数据库中,并在它认为最好的时候自动清理它。
您可以使用 workmanager.pruneWork()
自己进行清洁,但请按照文档中的说明谨慎使用。
我的逻辑是创建一个单一的工作链还是多个?
它创建单链,因为你正在使用
uniqeWork
和ExistingWorkPolicy.REPLACE
.
这样我的逻辑是否一致/可用?
我看不出有什么理由不应该,您创建了自己的周期性工作者实现,可以在不到 15 分钟的时间内执行。
为什么工人不使用 .cancelAllWorkByTag(TAG) 关闭?
如果它没有取消,很可能是您的代码。如文档中所述,取消是尽力而为,因此您需要检查它。 我会单独引用answer:
总而言之,如果你有一个尚未开始的待定工人, worker 将被取消并且不会运行。但是,如果工人是 已经在运行,取消工作不会终止 worker 硬时尚 - 它只是将工人的州旗设置为 已取消,如文档中所述。由您来处理 在你的 doWork 中取消并终止工作人员。
一种方法是在你的 doWork 方法中进行一些检查以 通过调用 isStopped() 检查 worker 是否被取消。如果 isStopped 为真,从方法返回结果而不是 继续其余的工作。
还要仔细检查是否使用了相同的标签。由于您使用的是
uniqueWork
,因此您也可以使用cancelUniqueWork
.