Dagger 的依赖注入被忽略,字段保持为空
Dagger's dependency injection ignored, field remains null
我有 2 个模块:AndroidModule
用于提供 Context
相关对象,PhotosModule
提供 PhotoManager
.
我想在 PhotosFragment
中使用 PhotoManager
。 PhotoManager
依赖于DbManager
,由AndroidModule
提供。
如何连接所有的点?
代码编译通过,但在该行抛出 NPE:
mDbManager.readDatabase();
意味着 DbManager
注入 PhotoManager
并没有发生,即使我设置了
injects = PhotoManager.class
在 AndroidModule
.
此外,mDbManager
不是私有字段,所以我认为我不必在 PhotoManager
的构造函数上使用注入;现场注入应该足够了。
这是什么原因以及如何满足缺少的依赖项?我假设我的代码可能存在不止一个问题。注意:我刚开始使用 Dagger,请记住这一点。
申请:
public class TestApp extends Application {
private ObjectGraph mObjectGraph;
@Override
public void onCreate() {
super.onCreate();
mObjectGraph = ObjectGraph.create(getModules().toArray());
}
protected List<Object> getModules() {
return Arrays.asList(new AndroidModule(this), new PhotosModule());
}
public void inject(Object object) {
mObjectGraph.inject(object);
}
}
安卓模块:
@Module(library = true, injects = PhotoManager.class)
public class AndroidModule {
private final TestApp mApplication;
public AndroidModule(TestApp application) {
mApplication = application;
}
@Provides
@Singleton
@ForApplication
Context provideApplicationContext() {
return mApplication;
}
@Provides
@Singleton
DbManager provideDbManager() {
return new DbManager(mApplication);
}
}
照片模块:
@Module(injects = PhotosFragment.class)
public class PhotosModule {
@Provides
@Singleton
PhotoManager providePhotoManager() {
return new PhotoManager();
}
}
照片管理器:
@Singleton
public class PhotoManager {
@Inject
DbManager mDbManager;
public void doSomething() {
mDbManager.readDatabase();
}
}
照片片段:
public class PhotosFragment extends Fragment {
@Inject
PhotoManager mPhotoManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((TestApp) getActivity().getApplication()).inject(this);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
///...
mPhotoManager.doSomething();
}
}
数据库管理器:
@Singleton
public class DbManager {
public DbManager(Context context) {
//...
}
public void readDatabase() {
//...
}
}
这是问题的核心:在 PhotosModule
中,您有提供程序方法:
PhotoManager providePhotoManager() {
return new PhotoManager();
}
您正在 new
自己启动 PhotoManager,因此 Dagger 没有机会注入其依赖项(DbManager
)。
我认为这是因为您误解了 AndroidModule
的 @Module(injects=...)
注释中 injects
属性 的含义。你有:
@Module(library = true, injects = PhotoManager.class)
但是不需要 injects
,因为您永远不会在 PhotoManager 上调用 objectGraph.inject。相反,您只注入 PhotoFragment
,这是正确的...
解决 NPE 问题的一种方法:
从 AndroidModule.java
中删除 injects=PhotoManager.class
:
@Module(library = true)
更改 PhotosModule
以包含 AndroidModule
:
@Module(injects = PhotosFragment.class, includes = AndroidModule.class)
我避免使用 @Inject
注释进行字段注入(仅将其用于顶级对象,即您执行 objectgraph.inject 的位置,例如 activity 和片段级别),并使用构造函数注入代替所有其他依赖项。所以我会改变 PhotoManager
来注入 DbManager
像这样:
private final DbManager mDbManager;
public PhotoManager(DbManager dbManager) {
mDbManager = dbManager;
}
我已经提供了代码 here on GitHub。
我有 2 个模块:AndroidModule
用于提供 Context
相关对象,PhotosModule
提供 PhotoManager
.
我想在 PhotosFragment
中使用 PhotoManager
。 PhotoManager
依赖于DbManager
,由AndroidModule
提供。
如何连接所有的点?
代码编译通过,但在该行抛出 NPE:
mDbManager.readDatabase();
意味着 DbManager
注入 PhotoManager
并没有发生,即使我设置了
injects = PhotoManager.class
在 AndroidModule
.
此外,mDbManager
不是私有字段,所以我认为我不必在 PhotoManager
的构造函数上使用注入;现场注入应该足够了。
这是什么原因以及如何满足缺少的依赖项?我假设我的代码可能存在不止一个问题。注意:我刚开始使用 Dagger,请记住这一点。
申请:
public class TestApp extends Application {
private ObjectGraph mObjectGraph;
@Override
public void onCreate() {
super.onCreate();
mObjectGraph = ObjectGraph.create(getModules().toArray());
}
protected List<Object> getModules() {
return Arrays.asList(new AndroidModule(this), new PhotosModule());
}
public void inject(Object object) {
mObjectGraph.inject(object);
}
}
安卓模块:
@Module(library = true, injects = PhotoManager.class)
public class AndroidModule {
private final TestApp mApplication;
public AndroidModule(TestApp application) {
mApplication = application;
}
@Provides
@Singleton
@ForApplication
Context provideApplicationContext() {
return mApplication;
}
@Provides
@Singleton
DbManager provideDbManager() {
return new DbManager(mApplication);
}
}
照片模块:
@Module(injects = PhotosFragment.class)
public class PhotosModule {
@Provides
@Singleton
PhotoManager providePhotoManager() {
return new PhotoManager();
}
}
照片管理器:
@Singleton
public class PhotoManager {
@Inject
DbManager mDbManager;
public void doSomething() {
mDbManager.readDatabase();
}
}
照片片段:
public class PhotosFragment extends Fragment {
@Inject
PhotoManager mPhotoManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((TestApp) getActivity().getApplication()).inject(this);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
///...
mPhotoManager.doSomething();
}
}
数据库管理器:
@Singleton
public class DbManager {
public DbManager(Context context) {
//...
}
public void readDatabase() {
//...
}
}
这是问题的核心:在 PhotosModule
中,您有提供程序方法:
PhotoManager providePhotoManager() {
return new PhotoManager();
}
您正在 new
自己启动 PhotoManager,因此 Dagger 没有机会注入其依赖项(DbManager
)。
我认为这是因为您误解了 AndroidModule
的 @Module(injects=...)
注释中 injects
属性 的含义。你有:
@Module(library = true, injects = PhotoManager.class)
但是不需要 injects
,因为您永远不会在 PhotoManager 上调用 objectGraph.inject。相反,您只注入 PhotoFragment
,这是正确的...
解决 NPE 问题的一种方法:
从
AndroidModule.java
中删除injects=PhotoManager.class
:@Module(library = true)
更改
PhotosModule
以包含AndroidModule
:@Module(injects = PhotosFragment.class, includes = AndroidModule.class)
我避免使用
@Inject
注释进行字段注入(仅将其用于顶级对象,即您执行 objectgraph.inject 的位置,例如 activity 和片段级别),并使用构造函数注入代替所有其他依赖项。所以我会改变PhotoManager
来注入DbManager
像这样:private final DbManager mDbManager; public PhotoManager(DbManager dbManager) { mDbManager = dbManager; }
我已经提供了代码 here on GitHub。