匕首2和界面的实现

我有一个简单的Dagger 2testing设置,基于http://konmik.github.io/snorkeling-with-dagger-2.html 。 它注入一个PreferenceLogger,输出所有的偏好。 在注入的类中,我可以@注入更多的类。

public class MainActivity extends Activity { @Inject PreferencesLogger logger; @Inject MainPresenter presenter; @Override protected void onCreate(Bundle savedInstanceState) { MyApplication.getComponent().inject(this); presenter.doStuff(); logger.log(this); } } public class PreferencesLogger { @Inject OkHttpClient client; @Inject public PreferencesLogger() {} public void log(Contect context) { // this.client is available } } 

当我运行这个,logging器被设置,并在PreferencesLogger.log OkHttpClient被正确设置。 所以这个例子按预期工作。 现在我正在尝试获得一个MVP结构。 有一个MainPresenter接口和一个实现。 在MainActivity中,我设置了一个:

 @Inject MainPresenter presenter; 

所以我可以用另一个(debugging或testing)实现来切换这个MainPresenter。 当然,现在我需要一个模块来指定我想要使用的实现。

 public interface MainPresenter { void doStuff(); } public class MainPresenterImpl implements MainPresenter { @Inject OkHttpClient client; public MainPresenterImpl() {} @Override public void doStuff() { // this.client is not available } } @Module public class MainActivityModule { @Provides MainPresenter provideMainPresenter() { return new MainPresenterImpl(); } } 

OkHttpClient不再被注入,现在出现了一个问题。 当然,我可以改变模块接受一个参数OkHttpClient,但我不认为这是build议的方式来做到这一点。 MainPresenterImpl不能正确注入的原因是什么?

与构造函数注入不同, @Provides方法中构造的@Inject注释@Provides字段不能被自动注入。 能够注入字段需要一个在其模块中提供字段types的组件,而在提供者方法本身中,这样的实现是不可用的。

MainActivity注入presenter字段时,所发生的一切就是调用提供者方法,并将presenter设置为其返回值。 在你的例子中,无参数构造函数没有初始化,提供者方法也没有,因此不进行初始化。

然而,提供者方法可以通过参数访问模块中提供的其他types的实例。 我认为在提供者方法中使用参数实际上是“注入”所提供的types的依赖关系的build议(甚至是唯一的)方式,因为它明确地将它们表示为模块内的依赖关系,这允许Dagger在编译时抛出错误如果他们不能满足的话。

它目前没有抛出错误的原因是因为MainPresenterImpl 可以得到它的OkHttpClient依赖性,如果MainPresenterImpl而不是MainPresenter是注入目标的某个地方。 Dagger不能为接口types创build成员注入方法,因为作为一个接口,它不能注入字段,也不会自动注入实现types的字段,因为它只是提供任何提供者方法回报。

您可以使用构造函数注入来注入您的MainPresenterImpl

 /* unscoped */ public class MainPresenterImpl implements MainPresenter { @Inject OkHttpClient client; @Inject public MainPresenterImpl() { } @Override public void doStuff() { // this.client is now available! :) } } @Module public class AppModule { private MyApplication application; public AppModule(MyApplication application) { this.application = application; } @Provides /* unscoped */ public MyApplication application() { return application; } } @Module public abstract class MainActivityModule { @Binds public abstract MainPresenter mainPresenter(MainPresenterImpl mainPresenterImpl); }