我正在学习 Udacity Android Kotlin 开发人员课程。在其中一课中,讲师教授了如何使用 WorkManager 执行后台任务,始终在后台缓存数据,以便在应用程序启动时显示新数据。
因此,启动 WorkManager 定期刷新数据的代码是在应用程序的主应用程序中定义的。
class DevByteApplication : Application() {
/**
* onCreate is called before the first screen is shown to the user.
*
* Use it to setup any background tasks, running expensive setup operations in a background
* thread to avoid delaying app start.
*/
val applicationScope = CoroutineScope(Dispatchers.Default)
override fun onCreate() {
super.onCreate()
Timber.plant(Timber.DebugTree())
delayedInit()
}
private fun delayedInit() = applicationScope.launch {
setupRecurringWork()
}
private fun setupRecurringWork() {
val constraints = …Run Code Online (Sandbox Code Playgroud) 我想在确切的时间定期向用户发送离线通知(假设每天上午9:00).现在我正在尝试工作管理器Api,但无法找到任何方法,如AlarmsManager的setExact或setexactandallowwhileidle.
在我的情况下,只有repeatInterval选项是24(每天),但如何在确切的时间(早上9点)发送通知.
By referring to: Android WorkManager api for running daily task in Background
It uses the WorkManager.enqueueUniquePeriodicWork to ensure that PeriodicWorkRequest is not created multiple times.
example code:
val work = PeriodicWorkRequestBuilder<SyncWork>(15,TimeUnit.MINUTES).build()
WorkManager.getInstance().enqueueUniquePeriodicWork("TaskTag",
ExistingPeriodicWorkPolicy.KEEP, work);
Run Code Online (Sandbox Code Playgroud)
However, I found it there is 2 option of ExistingPeriodicWorkPolicy which is ExistingPeriodicWorkPolicy.KEEP and ExistingPeriodicWorkPolicy.REPLACE can be use.
I try to implement it and run the code, but it does really show any differences, and it seem both of them behave the same way.
My uncertainty: …
WorkManager 对同时运行的作业数量是否有上限?
非常简单的例子:
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
queue.setOnClickListener {
val jobs = mutableListOf<OneTimeWorkRequest>()
for( i in 1..10 ) {
jobs += OneTimeWorkRequestBuilder<MyWorker>()
.setInputData(workDataOf("key" to i))
.build()
}
WorkManager.getInstance().enqueue(jobs)
}
}
}
class MyWorker: Worker() {
override fun doWork(): Result {
val jobId = inputData.getInt("key", -1)
Log.d("worker", "starting job: $jobId")
Completable.timer(10, SECONDS).blockingGet()
Log.d("worker", "job finished: $jobId")
return SUCCESS
}
}
Run Code Online (Sandbox Code Playgroud)
和输出:
08-30 14:03:10.392 9825 9855 …Run Code Online (Sandbox Code Playgroud) 我使用此代码设置我自己的工厂工厂:
val daggerWorkerFactory = DaggerWorkerFactory(toInjectInWorker)
val configuration = Configuration.Builder()
.setWorkerFactory(daggerWorkerFactory)
.build()
WorkManager.initialize(context, configuration)
Run Code Online (Sandbox Code Playgroud)
执行此代码后,我可以获取WorkManager实例:
val workManager = WorkManager.getInstance()
Run Code Online (Sandbox Code Playgroud)
问题是,对于在此之后创建的每个工人,我的工厂从未使用过.而是使用默认工厂.
我可以在API文档中看到方法"WorkManager.initialize"有一个注释:
在清单中禁用androidx.work.impl.WorkManagerInitializer
我找不到任何有关如何执行此操作的信息.这是在一些旧版本的WorkManager上,他们忘了从文档中删除或这是否真的有必要?如果是这样,怎么样?
我有 3 个任务 A、B 和 C。我想观察这条链的实时数据,并有一个进度条显示正在进行的工作,一旦工作完成,它应该禁用进度条。
// One Time work for A class
OneTimeWorkRequest Awork = new OneTimeWorkRequest
.Builder(A.class)
.setConstraints(Miscellaneous.networkConstraint())
.addTag("A")
.build();
//same for B and C
//work chain
WorkContinuation syncChain = WorkManager.getInstance()
.beginWith(Awork)
.then(Bwork)
.then(Cwork);
syncChain.enqueue();
Run Code Online (Sandbox Code Playgroud) 我将PeriodicWorkRequest设置为15分钟.但它有时重复10次有时17分钟.如何设置最大几秒的偏差.
val workRequest = PeriodicWorkRequest.Builder(NotificationWork::class.java, 15, TimeUnit.MINUTES).build()
WorkManager.getInstance().enqueue(workRequest)
Run Code Online (Sandbox Code Playgroud)
13:10
13:26
13:51
14:01
我可以在刻度线上设置一个类似闹钟的后台工作,否则Workmanager会像这样工作吗?
我的代码块就像上面一样.
IllegalAccessException当尝试使WorkManager 1.0稳定版入队时,我得到了。这是堆栈跟踪:
E/WM-WorkerFactory: Could not instantiate com.pocket.sdk.util.service.BackgroundSync$SyncJob
java.lang.IllegalAccessException: java.lang.Class<com.example.BackgroundManager$BackgroundWorker> is not accessible from java.lang.Class<androidx.work.WorkerFactory>
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:92)
at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:233)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:127)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Run Code Online (Sandbox Code Playgroud)
worker是一个内部类,声明如下:
E/WM-WorkerFactory: Could not instantiate com.pocket.sdk.util.service.BackgroundSync$SyncJob
java.lang.IllegalAccessException: java.lang.Class<com.example.BackgroundManager$BackgroundWorker> is not accessible from java.lang.Class<androidx.work.WorkerFactory>
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.work.WorkerFactory.createWorkerWithDefaultFallback(WorkerFactory.java:92)
at androidx.work.impl.WorkerWrapper.runWorker(WorkerWrapper.java:233)
at androidx.work.impl.WorkerWrapper.run(WorkerWrapper.java:127)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Run Code Online (Sandbox Code Playgroud)
如何解决此异常?
具有以下依赖性:
dependencies {
implementation "androidx.work:work-runtime:2.0.1"
androidTestImplementation "androidx.work:work-testing:2.0.1"
}
Run Code Online (Sandbox Code Playgroud)
当第二次运行此代码时:
Configuration config = new Configuration.Builder().build();
WorkManager.initialize(getApplicationContext(), config);
this.workManager = WorkManager.getInstance();
Run Code Online (Sandbox Code Playgroud)
我收到此错误消息:
java.lang.IllegalStateException: WorkManager is already initialized.
Did you try to initialize it manually without disabling WorkManagerInitializer?
See WorkManager#initialize(Context, Configuration) or the class level Javadoc for more information.
Run Code Online (Sandbox Code Playgroud)
并且还会在本机端引发分段错误:
A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR),
fault addr 0x878 in tid 10892 (ova.workmanager),
pid 10892 (ova.workmanager)
Run Code Online (Sandbox Code Playgroud)
这将是文档的WorkManager#initialize(Context, Configuration)。
目的是防止在手动初始化期间崩溃(以更改日志级别)。如何禁用WorkManagerInitializer?如果可能的话,我不想使用static关键字。
java android illegalstateexception android-workmanager androidx
似乎 ListenableWorker 不再具有 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 限制,但是我无法弄清楚或找到有关如何在我覆盖的 startWork() 函数中正确返回 ListenableFuture< Result> 的示例。
据我所知,唯一的选择是返回一个 SettableFuture.create<Result>() 但这仍然需要抑制“RestrictedApi”警告/错误。
有人知道更简单的方法吗?
编辑:据我所知,这是使用 CallbackToFutureAdapter.Completer 的方法
override fun startWork(): ListenableFuture<Result> {
return CallbackToFutureAdapter.getFuture({
it.set(ListenableWorker.Result.success())
})
}
Run Code Online (Sandbox Code Playgroud)