Dagger2:无法在 WorkManager 中注入依赖项 [英] Dagger2: Unable to inject dependencies in WorkManager

查看:40
本文介绍了Dagger2:无法在 WorkManager 中注入依赖项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以从我读到的内容来看,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.

假设您有一个名为 DataClearingWorkerWorker 子类,并且该类需要来自您的 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
    }
}

最后,您需要创建一个可以访问 FooDaggerWorkerFactory.你可以用普通 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 中注入依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆