使用Dagger2注入后字段为null?如何正确实现对象注入?
你的问题核心在于手动创建了Presenter实例,跳过了Dagger的字段注入流程,同时混淆了构造函数注入和字段注入的正确使用方式。咱们一步步拆解问题,然后给出靠谱的实现方案。
为什么Context会是Null?
先看你的MyModule代码:
@Module class MyModule { @Provides MyPresenter provideMyPresenter(MyView view) { return new MyPresenter(view); } }
这里你直接new MyPresenter(view),相当于把对象创建的控制权从Dagger手里抢过来了——Dagger只会对它自己创建的对象执行字段注入操作。你手动new出来的实例,Dagger根本不知道它的存在,自然不会帮你注入Context字段,这就是空指针的根源。
另外,你的MyPresenter已经标注了@Inject构造函数,这时候其实完全不需要在Module里写@Provides方法,Dagger可以自动通过构造函数创建实例,前提是你得让Dagger接管创建过程。
正确的实现步骤
第一步:修正Presenter的注入逻辑
保留@Inject构造函数,确保Dagger能通过构造函数创建实例,同时处理Context依赖:
class MyPresenter { @Inject Context context; private MyView view; // 让Dagger通过这个构造函数创建实例,自动注入MyView @Inject MyPresenter(MyView view) { this.view = view; } }
第二步:精简Module,只提供Dagger无法自动生成的依赖
因为Presenter已经有@Inject构造函数,MyModule里不需要再写provideMyPresenter了。只需要提供Dagger无法自动获取的依赖(比如Context、MyView):
@Module class MyModule { // 提供ApplicationContext,避免持有Activity引用导致内存泄漏 @Provides Context provideContext(MyActivity activity) { return activity.getApplicationContext(); } // 提供MyView实例(假设MyActivity实现了MyView接口) @Provides MyView provideMyView(MyActivity activity) { return activity; } }
第三步:配置Component关联Module和注入目标
你的Component需要关联Module,并且声明对Activity的注入方法:
@Component(modules = MyModule.class) interface MyActivityComponent { void inject(MyActivity activity); }
第四步:在Activity中完成正确注入
保持Activity的注入逻辑,注意使用Dagger自动生成的Component类(格式为DaggerXXXComponent):
class MyActivity extends Activity implements MyView { @Inject MyPresenter presenter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 让Dagger创建Component并完成注入 DaggerMyActivityComponent.create().inject(this); // 现在presenter和presenter.context都应该不为null了 } }
关键知识点:构造函数注入 vs 字段注入
- 构造函数注入:这是Dagger最推荐的方式,依赖通过构造函数传入,对象创建时就完成依赖注入,从根源避免空指针。只要构造函数加
@Inject,Dagger会自动寻找所需依赖来创建实例。 - 字段注入:一般用于系统创建的类(比如Activity、Fragment),这些类的实例不由我们控制,只能用字段注入。但对于你自己写的业务类(比如Presenter),优先用构造函数注入更稳妥。
如果非要在Presenter里用字段注入Context,核心前提还是得让Dagger来创建Presenter实例——去掉Module里的手动创建逻辑,Dagger会自动完成构造函数注入+字段注入的全套流程。
内容的提问来源于stack exchange,提问作者David Medenjak

