匕首不使用无效方法进行注射

时间:2018-08-29 12:27:02

标签: dagger-2 dagger

我有应用范围内的组件(仅包含Singletons),可以通过静态方法App.getComponent();访问。我的组件包含方法void inject(MainActivity activity),它工作正常。我也有void inject(TaskRepo repo),但是这个不起作用。在TaskRepoImpl()中,我调用:App.getComponent().inject(this);,但它不会注入任何东西。我确定我用@Inject注释了公共成员。

使用TaskRepo repo = App.getComponent().taskRepo();之类的方法注入效果很好。那么,为什么匕首会忽略这些成员?

1 个答案:

答案 0 :(得分:1)

简而言之,您需要将方法设为void inject(TaskRepoImpl impl);您不能只接受TaskRepo。 in the Component docs under "A note about covariance"说明了您的情况。

Dagger是一个编译时框架:在 compile时 Dagger将查看您的Component并根据Component(及其Modules)上的方法编写实现。其中一些方法可能是members injection methods(与上面的链接相同),它们是单参数方法,用于设置@Inject字段并为传入的实例调用@Inject方法。这些通常是void个名为inject的方法,但是它们可以命名为任何东西,它们也可能返回它们注入的实例(用于链接)。

诀窍是, Dagger只能预见您定义的特定类型上的字段和方法,而不能预见其子类:如果创建成员注入方法void inject(Foo foo),则只有Foo可以即使Foo的子类Bar具有@Inject注释的方法,字段和方法也很重要。即使您的Dagger图同时了解Foo和Bar,也不会了解其他Foo子类,也不必准备注入它们(因为所有这些都在编译时发生)。对于“供应方法”(组件上的零参数工厂/ getter)来说,这也不是问题,因为只要Dagger知道如何为绑定创建特定的具体类型,它就可以注入该具体类型并将其返回为其超类型或接口。

因此,将注入切换到实际实现类可以避免此问题,因为Dagger可以在编译时检查实现类TaskRepoImpl,并确保它具有TaskRepoImpl在其{{1}中定义的绑定}注释的方法和字段。

@Inject

作为补充,构造函数注入使您可以通过使用@Component(modules = {...}) public interface YourComponent { /** * Only injects the fields and methods on TaskRepo, which might do * nothing--especially if TaskRepo is just an interface. */ void inject(TaskRepo taskRepo); /** * Injects the fields and methods on TaskRepoImpl, TaskRepo, and * any other superclasses or interfaces. */ void inject(TaskRepoImpl taskRepoImpl); /** * Gets a TaskRepo implementation. If you've bound TaskRepo to TaskRepoImpl, * Dagger _can_ inject all of TaskRepoImpl's fields, because it knows at * compile time that there's a TaskRepoImpl instance to inject. */ TaskRepo taskRepo(); } 字段并避免部分构造(构造但未注入)实例更好地封装类。我建议在可能的情况下使用构造函数注入,强烈建议不要对同一种类型的字段注入和构造函数注入使用 。 (除了调试您的案例,您可能没有做其他事情,但是我在这里也留了注释,以供将来的读者使用。)