Dagger 2 和接口实现
Dagger 2 and interface implementations
我有一个简单的 Dagger 2 测试设置,基于 http://konmik.github.io/snorkeling-with-dagger-2.html。
它注入一个输出所有首选项的 PreferenceLogger。在注入的class中,我可以@Inject more classes.
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
}
}
当我 运行 设置记录器时,在 PreferencesLogger.log 中正确设置了 OkHttpClient。
所以这个例子按预期工作。
现在,我正在尝试建立一个 MVP 结构。
有一个带有实现的 MainPresenter 接口。在 MainActivity 中我设置了一个:
@Inject MainPresenter presenter;
所以我可以用替代(调试或测试)实现切换此 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,但我认为这不是建议的方法。 MainPresenterImpl 无法正确注入是否有原因?
与构造函数注入不同,无法自动注入在 @Provides
方法中构造的依赖项的 @Inject
注释字段。能够注入字段需要一个在其模块中提供字段类型的组件,而在提供者方法本身中,这样的实现是不可用的。
当 presenter
字段被注入 MainActivity
时,所发生的只是调用提供者方法并将 presenter
设置为其 return 值。在您的示例中,无参数构造函数不进行初始化,提供程序方法也不进行初始化,因此不进行初始化。
但是,提供者方法确实可以通过其参数访问模块中提供的其他类型的实例。我认为在 provider 方法中使用参数实际上是 "inject" 所提供类型的依赖项的建议(甚至是唯一)方法,因为它明确地将它们指示为模块中的依赖项,这允许 Dagger 抛出错误如果不能满足,则在编译时。
它目前没有抛出错误的原因是因为 MainPresenterImpl
可以 满足其 OkHttpClient
依赖关系,如果 MainPresenterImpl
而不是MainPresenter
是某个地方的注入目标。 Dagger 不能为接口类型创建成员注入方法,因为作为一个接口,它不能有可注入字段,它不会自动注入实现类型的字段,因为它只是提供任何提供者方法returns.
您可以使用构造函数注入来注入您的 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);
}
我有一个简单的 Dagger 2 测试设置,基于 http://konmik.github.io/snorkeling-with-dagger-2.html。 它注入一个输出所有首选项的 PreferenceLogger。在注入的class中,我可以@Inject more classes.
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
}
}
当我 运行 设置记录器时,在 PreferencesLogger.log 中正确设置了 OkHttpClient。 所以这个例子按预期工作。 现在,我正在尝试建立一个 MVP 结构。 有一个带有实现的 MainPresenter 接口。在 MainActivity 中我设置了一个:
@Inject MainPresenter presenter;
所以我可以用替代(调试或测试)实现切换此 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,但我认为这不是建议的方法。 MainPresenterImpl 无法正确注入是否有原因?
与构造函数注入不同,无法自动注入在 @Provides
方法中构造的依赖项的 @Inject
注释字段。能够注入字段需要一个在其模块中提供字段类型的组件,而在提供者方法本身中,这样的实现是不可用的。
当 presenter
字段被注入 MainActivity
时,所发生的只是调用提供者方法并将 presenter
设置为其 return 值。在您的示例中,无参数构造函数不进行初始化,提供程序方法也不进行初始化,因此不进行初始化。
但是,提供者方法确实可以通过其参数访问模块中提供的其他类型的实例。我认为在 provider 方法中使用参数实际上是 "inject" 所提供类型的依赖项的建议(甚至是唯一)方法,因为它明确地将它们指示为模块中的依赖项,这允许 Dagger 抛出错误如果不能满足,则在编译时。
它目前没有抛出错误的原因是因为 MainPresenterImpl
可以 满足其 OkHttpClient
依赖关系,如果 MainPresenterImpl
而不是MainPresenter
是某个地方的注入目标。 Dagger 不能为接口类型创建成员注入方法,因为作为一个接口,它不能有可注入字段,它不会自动注入实现类型的字段,因为它只是提供任何提供者方法returns.
您可以使用构造函数注入来注入您的 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);
}