【问题标题】:Dagger & nested injections匕首和嵌套注入
【发布时间】:2013-07-15 11:17:29
【问题描述】:

我正在使用Dagger 将依赖项注入到 Android 应用程序,我偶然发现了一个我不完全确定的问题 如何以干净的方式解决。

我想要实现的是实例化助手并将它们注入我的 活动,并让这些助手也包含注入的成员。

什么有效

我的助手被注入的活动:

public class MyActivity extends Activity {
    @Inject SampleHelper helper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ((MyApplication) getApplication()).inject(this);

        Log.i("debug", "helper = " + helper);
        Log.i("debug", "helper context = " + helper.context);
    }
}

创建对象图的应用程序:

public class MyApplication extends Application {
    private ObjectGraph graph;

    @Override
    public void onCreate() {
        super.onCreate();

        graph = ObjectGraph.create(getModules());
    }

    private Object[] getModules() {
        return new Object[] { new MyModule(this) };
    }

    public void inject(Object target) {
        graph.inject(target);
    }
}

当我直接实例化 SampleHelper 类时,注入工作完美, 它又接收注入的应用程序上下文:

@Singleton
public class SampleHelper {

    @Inject public Context context;

    @Inject
    public SampleHelper() {}
}

使用以下模块:

@Module(
    injects = { MyActivity.class },
    complete = false,
    library = true
)
public class MyModule {
    private final MyApplication application;

    public MyModule(MyApplication application) {
      this.application = application;
    }

    @Provides @Singleton Context provideApplicationContext() {
        return application;
    }
}

什么不起作用

但是,当我将帮助接口与其实现分开时:

public interface SampleHelper {
}

@Singleton
public class SampleHelperImpl implements SampleHelper {

    @Inject public Context context;

    @Inject
    public SampleHelperImpl() {}
}

并将其添加到匕首模块:

public class MyModule {
    ...

    // added this method
    @Provides @Singleton public SampleHelper provideSampleHelper() {
        return new SampleHelperImpl();
    }

    ...
}

上下文没有像我预期的那样被注入到我的 SampleHelperImpl 中。现在,我想这是由于 SampleHelperImpl 通过直接构造函数调用而不是 那个注入启动的构造函数调用,因为 MyModule#provideApplicationContext() 甚至没有被调用,所以我猜我错过了关于 Dagger 的一些东西(这很可能,因为我以前的 DI 经验只包括 Spring)。

关于如何以“干净的 Dagger”方式将我的上下文注入到我的注入助手实现中的任何想法?

非常感谢!

【问题讨论】:

  • 我现在也在用匕首苦苦挣扎,和你的配置相似。我需要将活动实例注入帮助程序,而不是应用程序本身,否则它非常相似。这就是为什么我要问你一个问题:为什么要将上下文作为成员注入SampleHelper,而不是作为构造函数参数?就我而言,通过构造函数参数注入失败,因此我想知道它是否有什么特别之处,应该避免。我知道这是题外话,但如果您能提供帮助,我们将不胜感激。
  • 实际上,我现在将上下文作为构造函数参数传递(如下面的回答中所述),尽管它不是直接注入构造函数本身,而是作为@Provides 方法的一部分匕首模块(并且它有效)。我最初的想法是放弃所有与分配我的成员相关的代码,这要归功于 dagger,但我无法让它像 spring-injection 那样易于使用。话虽如此,我知道它们的工作方式和约束不同,但匕首仍然带来了很多。
  • 您好,感谢您的回复。也许你可以看看我的问题? stackoverflow.com/questions/17839451/…

标签: android dependency-injection dagger


【解决方案1】:

这是一个相当古老的问题,但我认为您想要的是:

@Provides @Singleton public SampleHelper provideSampleHelper(SampleHelperImpl impl) {
    return impl;
}

这样 Dagger 将创建您的 SampleHelperImpl 并因此注入它。

【讨论】:

  • 还不算太晚:它确实完美地回答了我的问题。非常感谢!
  • @alexanderblom 你能解释一下你所做的和 mrlem 所做的区别吗?
【解决方案2】:

如果有人感兴趣,在 dagger 模块中实现 @Provides 方法时,您可以像这样获得 dagger-handled objects 实例:

@Provides @Singleton public SampleHelper provideSampleHelper(Context context) {
    SampleHelper helper = new SampleHelperImpl();
    helper.setContext(context);
    return helper;
}

这行得通,但我仍然觉得它有点笨拙,因为我必须明确地调用我的助手设置器(通常是你想通过注入摆脱的东西)。

(我会稍等一下,以防有人提出更好的解决方案)

【讨论】:

    【解决方案3】:

    (适用于 Dagger v1.0.1)

    确保您使用的是适配器注入。通过反射注入,dagger 显然不会对 @Provides 对象进行传递注入。我认为这是一个错误。

    【讨论】:

    • 这听起来很像我的问题。但是您能否澄清两件事:1/我认为它没有使用反射进行注入? (我想这就是“反射注入”的意思,还是您的意思是基于注释的注入?) 2/适配器注入是什么意思:在 dagger 模块中使用 @Provides 进行注入?
    • Dagger 提供了两种设置@Inject注解字段的方式。一种是通过反射,另一种是通过生成的适配器类。在这两种情况下,这些字段至少需要包可访问。反射方法是一种后备方法,可能在未来版本中不可用。要检查您使用的注入方法,请在模块的 @Provides 方法中设置断点,然后检查堆栈跟踪。注意:injectMembers():118, ReflectiveAtInjectBinding {dagger.internal.plugins.reflect}injectMembers():82, YourClassname$$InjectAdapter {your.classes.package}
    【解决方案4】:

    关于注入正确的上下文,您可能想看看这个示例https://github.com/square/dagger/tree/master/examples/android-activity-graphs

    【讨论】:

    • 感谢您的回复:我已经遇到过这个例子(它们的数量并不多;)。事实上,在现实生活中的应用程序中,您需要注入正确的上下文。但是我最初的问题有点笼统:将 Helper 接口与实现分开会阻止 @Inject 在实现中工作,因为 Dagger 不再直接处理 helper 实例化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-04
    • 1970-01-01
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多