【发布时间】:2015-10-03 17:59:22
【问题描述】:
我目前正在尝试将 Dagger 2 集成到 Android 应用程序中。我的项目设置如下:
- 图书馆
- 应用程序(取决于库)
在我的库项目中,我定义了一个类,稍后我将注入到库中其他需要它的类(活动和常规类)以及应用程序项目中。
@Singleton
public class MyManager{
@Inject
public MyManager(){
//Do some initializing
}
}
现在 - 例如在我的片段或活动或常规课程中,我将注入上述单例,如下所示:
public class SomeClass{
@Inject
MyManager myManager;
}
我是这么想的,因为实际上 myManager 总是为空。显然它的构造函数也从未被调用过,所以我想我一定是在配置方面遗漏了一些东西?或者也许我误解了文档,它根本不打算以这种方式工作? MyManager 类的目的是成为一个应用程序范围内可访问的组件累积实体——这就是我选择@Singleton 的原因。
更新
为了避免混淆:我在评论的某处提到了我的组件——这是指“基于组件的设计”意义上的组件,与匕首无关。我拥有的基于 dagger 的代码都在上面列出 - 在我的代码中没有其他与 dagger 相关的内容。
当我开始添加 @Component 时,我遇到了一些编译器问题,因为我的 dagger2 没有正确设置 - 查看这个关于如何正确设置 dagger2 的非常有用的线程:https://stackoverflow.com/a/29943394/1041533
更新 2
这是我根据 G. Lombard 的建议更新的代码 - 我将代码更改如下 - 原来的 Singleton 在库项目中:
@Singleton
public class MyManager{
@Inject
public MyManager(){
//Do some initializing
}
}
库项目中还有引导类:
@Singleton
@Component
public interface Bootstrap {
void initialize(Activity activity);
}
然后我在我的活动中使用上面的 Bootstrap 类(在我的具体应用程序中,NOT 在库项目中!但是我在库中也有类/活动,它们将访问 Bootstrap 以注入我的经理):
public class MyActivity extends Activity{
@Inject
MyManager manager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//DONT DO THIS !!! AS EXPLAINED BY EpicPandaForce
DaggerBootstrap.create().initialize(this);
}
}
但即使在这行之后:
DaggerBootstrap.create().initialize(this);
管理器实例仍为空,即未注入。
我刚刚发现了这个:https://stackoverflow.com/a/29326023/1041533
如果我没有误读,这意味着我需要指定 Bootstrap 类中的每个类,这些类将使用 @Inject 来注入东西。可悲的是 - 这不是一个选择,因为我有 40 多个课程和活动我必须这样做。
这意味着我的 Bootstrap 界面显然必须看起来像这样:
@Singleton
@Component
public interface Bootstrap {
void initialize(ActivityA activity);
void initialize(ActivityB activity);
void initialize(ActivityC activity);
void initialize(ActivityD activity);
void initialize(ActivityE activity);
void initialize(ActivityF activity);
//and so on and so forth...
}
如果上述情况属实,那对于我的用例来说就不值得了。另外:如果我忘记在这里指定我的 40 多个类之一,似乎没有编译时检查?它只是不起作用 - 即在运行时使应用程序崩溃。
【问题讨论】:
-
您对“没有编译时检查”的假设是不正确的,除非您为同一个类同时指定超类和具体类(即编译检查开始失败并且您需要警惕空值)。这不是匕首1。
-
啊。那么你需要手动调用现场注入。编译时检查是,如果您尝试使用组件注入一个类,那么它需要定义一个
void inject(YourClass yourClass);方法,否则它将无法工作。回到 Dagger1 的时代,你必须在injects={YourClass.class}类型的数组中提供它,如果你搞砸了,它实际上确实会引发运行时异常!这很糟糕。我们在 ApplicationComponent 中定义了大约 53 个用于字段注入的类,并且提供的类(非生命周期)可以在其构造函数中调用注入。瞧! -
好吧,他们需要在创建时手动调用组件的注入方法。如果他们真的记得调用
inject,那么它会抱怨需要如何将它添加到组件中。我想说“他们忘记注入”就像说“我用注释标记了视图字段,但我的视图为空”,因为他们忘记在setContentView(R.layout.something);之后调用ButterKnife.bind(this);... 他们会发现这是有点需要让它工作。我的同事对匕首(和依赖注入)完全陌生,他很快就学会了。 -
你的
Bootstrap类是一个真正的匕首组件,它被这样注释。方法的名称无关紧要,可以调用inject或initialize或任何方法,只要它的返回类型是void并且参数是您要注入的任何参数。 -
@EpicPandaForce 非常感谢您清理这个问题!您的 cmets 对了解 dagger2 的工作原理非常有帮助!
标签: java android dagger dagger-2