问题描述
因此,据我所读,Dagger还不支持在Worker中插入.但是,正如人们建议的那样,有一些解决方法.我已经尝试了多种方法来遵循网上示例,但是没有一个对我有用.
当我不尝试向Worker类中注入任何内容时,代码可以正常工作,仅是因为我需要访问某些DAO和服务而无法做我想做的事情.如果我在这些依赖项上使用@Inject,则依赖项为null或工作程序从不启动,即调试器甚至都没有进入Worker类.
例如,我尝试这样做:
@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依赖项将保持为空.
我尝试做许多其他事情,但没有任何效果.有没有办法做到这一点?谢谢!
概述
您需要查看从1.0.0-alpha09
开始可用的 WorkerFactory .
以前的解决方法依赖于能够使用默认的0-arg构造函数创建Worker
的方法,但是从1.0.0-alpha10
开始,这不再是一个选择.
示例
假设您有一个名为DataClearingWorker
的Worker
子类,并且该类需要Dagger图中的Foo
.
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
字段.
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
.您可以使用正常匕首的方式进行此操作.
@Provides
@Singleton
fun workerFactory(foo: Foo): WorkerFactory {
return DaggerWorkerFactory(foo)
}
禁用默认的WorkManager初始化
您还需要禁用默认的WorkManager
初始化(自动发生)并手动对其进行初始化.
在AndroidManifest.xml
中,您可以这样禁用它:
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="com.your.app.package.workmanager-init"
android:enabled="false"
android:exported="false"
tools:replace="android:authorities" />
请确保将 com.your.app.package 替换为实际应用的软件包.上方的<provider
块位于内部标签中..因此,它是Activities
,Services
等的同级兄弟.
在您的Application
子类中(或者,如果愿意,可以在其他位置),您可以手动初始化WorkManager
.
@Inject
lateinit var workerFactory: WorkerFactory
private fun configureWorkManager() {
val config = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
WorkManager.initialize(this, config)
}
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.
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.
For eg I tried doing this:
@Component(modules = {Module.class})
public interface Component{
void inject(MyWorker myWorker);
}
@Module
public class Module{
@Provides
public MyRepository getMyRepo(){
return new myRepository();
}
}
And in my worker
@Inject
MyRepository myRepo;
public MyWorker() {
DaggerAppComponent.builder().build().inject(this);
}
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!!
Overview
You need to look at WorkerFactory, available from 1.0.0-alpha09
onwards.
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.
Example
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
}
}
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
}
}
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)
}
Disabling Default WorkManager Initialization
You'll also need to disable the default WorkManager
initialization (which happens automatically) and initialize it manually.
In the AndroidManifest.xml
, you can disable it like this:
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="com.your.app.package.workmanager-init"
android:enabled="false"
android:exported="false"
tools:replace="android:authorities" />
Be sure to replace com.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...
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中注入依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!