Dagger 的依赖注入被忽略,字段保持为空

Dagger's dependency injection ignored, field remains null

我有 2 个模块:AndroidModule 用于提供 Context 相关对象,PhotosModule 提供 PhotoManager.

我想在 PhotosFragment 中使用 PhotoManagerPhotoManager依赖于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 问题的一种方法:

  1. AndroidModule.java 中删除 injects=PhotoManager.class:

    @Module(library = true)
    
  2. 更改 PhotosModule 以包含 AndroidModule:

    @Module(injects = PhotosFragment.class, includes = AndroidModule.class)
    
  3. 我避免使用 @Inject 注释进行字段注入(仅将其用于顶级对象,即您执行 objectgraph.inject 的位置,例如 activity 和片段级别),并使用构造函数注入代替所有其他依赖项。所以我会改变 PhotoManager 来注入 DbManager 像这样:

    private final DbManager mDbManager;
    
    public PhotoManager(DbManager dbManager) {
        mDbManager = dbManager;
    }
    

我已经提供了代码 here on GitHub