问题描述
所以从我读到的内容来看,Dagger 尚不支持在 Worker 中注入.但是正如人们所建议的那样,有一些解决方法.我已经尝试通过多种方式按照在线示例进行操作,但没有一种对我有用.
So from what I read, Dagger doesn't have support for inject in Worker yet. But there are some workarounds as people suggest. I have tried to do it a number of ways following examples online but none of them work for me.
当我不尝试向 Worker 类中注入任何东西时,代码运行良好,只是我不能做我想做的事,因为我需要访问一些 DAO 和服务.如果我在这些依赖项上使用 @Inject,依赖项要么为空,要么工作程序永远不会启动,即调试器甚至不进入 Worker 类.
When I don't try to inject anything into the Worker class, the code works fine, only that I can't do what I want because I need access to some DAOs and Services. If I use @Inject on those dependencies, the dependencies are either null or the worker never starts i.e the debugger doesn't even enter the Worker class.
例如,我尝试这样做:
@Component(modules = {Module.class})
public interface Component{
void inject(MyWorker myWorker);
}
@Module
public class Module{
@Provides
public MyRepository getMyRepo(){
return new myRepository();
}
}
在我的工作人员中
@Inject
MyRepository myRepo;
public MyWorker() {
DaggerAppComponent.builder().build().inject(this);
}
但是执行永远不会到达工作人员.如果删除构造函数,则 myRepo 依赖项仍为 null.
But then the execution never reaches the worker. If I remove the constructor, the myRepo dependency remains null.
我尝试了很多其他的事情,但都没有成功.有没有办法做到这一点?谢谢!!
I tried doing many other things but none work. Is there even a way to do this? Thanks!!
推荐答案
概述
您需要查看 WorkerFactory,可从 1.0 获得.0-alpha09
起.
以前的解决方法依赖于能够使用默认的 0-arg 构造函数创建 Worker
,但从 1.0.0-alpha10
开始,这不再是一个选项.
Previous workarounds relied on being able to create a Worker
using the default 0-arg constructor, but as of 1.0.0-alpha10
that is no longer an option.
假设您有一个名为 DataClearingWorker
的 Worker
子类,并且该类需要来自您的 Dagger 图的 Foo
.
Let's say that you have a Worker
subclass called DataClearingWorker
, and that this class needs a Foo
from your Dagger graph.
class DataClearingWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
lateinit var foo: Foo
override fun doWork(): Result {
foo.doStuff()
return Result.SUCCESS
}
}
现在,您不能直接实例化那些 DataClearingWorker
实例之一.所以你需要定义一个 WorkerFactory
子类,它可以为你创建其中之一;不仅要创建一个,还要设置您的 Foo
字段.
Now, you can't just instantiate one of those DataClearingWorker
instances directly. So you need to define a WorkerFactory
subclass that can create one of them for you; and not just create one, but also set your Foo
field too.
class DaggerWorkerFactory(private val foo: Foo) : WorkerFactory() {
override fun createWorker(appContext: Context, workerClassName: String, workerParameters: WorkerParameters): ListenableWorker? {
val workerKlass = Class.forName(workerClassName).asSubclass(Worker::class.java)
val constructor = workerKlass.getDeclaredConstructor(Context::class.java, WorkerParameters::class.java)
val instance = constructor.newInstance(appContext, workerParameters)
when (instance) {
is DataClearingWorker -> {
instance.foo = foo
}
// optionally, handle other workers
}
return instance
}
}
最后,您需要创建一个可以访问 Foo
的 DaggerWorkerFactory
.你可以用普通 Dagger方式来做到这一点.
Finally, you need to create a DaggerWorkerFactory
which has access to the Foo
. You can do this in the normal Dagger way.
@Provides
@Singleton
fun workerFactory(foo: Foo): WorkerFactory {
return DaggerWorkerFactory(foo)
}
禁用默认 WorkManager 初始化
您还需要禁用默认的 WorkManager
初始化(自动发生)并手动初始化.
Disabling Default WorkManager Initialization
You'll also need to disable the default WorkManager
initialization (which happens automatically) and initialize it manually.
您如何执行此操作取决于您使用的 androidx.work
版本:
How you do this depends on the version of androidx.work
that you're using:
在AndroidManifest.xml
中,添加:
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="YOUR_APP_PACKAGE.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
2.6.0 之前:
在AndroidManifest.xml
中,添加:
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="YOUR_APP_PACKAGE.workmanager-init"
android:enabled="false"
android:exported="false"
tools:replace="android:authorities" />
请务必将 YOUR_APP_PACKAGE 替换为您的实际应用程序包.上面的 <provider
块位于 inside <application
标签......所以它是你的 Activity
的兄弟, Services
等...
Be sure to replace YOUR_APP_PACKAGE with your actual app's package. The <provider
block above goes inside your <application
tag.. so it's a sibling of your Activities
, Services
etc...
在您的 Application
子类中(或其他地方,如果您愿意),您可以手动初始化 WorkManager
.
In your Application
subclass, (or somewhere else if you prefer), you can manually initialize WorkManager
.
@Inject
lateinit var workerFactory: WorkerFactory
private fun configureWorkManager() {
val config = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
WorkManager.initialize(this, config)
}
这篇关于Dagger2:无法在 WorkManager 中注入依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!