R. *_*ang 7 java mvp android dependency-injection dagger-2
我有一个简单的Dagger 2测试设置,基于http://konmik.github.io/snorkeling-with-dagger-2.html.它注入一个PreferenceLogger,输出所有的首选项.在注入的类中,我可以@Inject更多的类.
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
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时,设置了记录器,并在PreferencesLogger.log中正确设置了OkHttpClient.所以这个例子按预期工作.现在我正试图建立一个MVP结构.有一个实现的MainPresenter接口.在MainActivity中我设置了一个:
@Inject MainPresenter presenter;
Run Code Online (Sandbox Code Playgroud)
所以我可以用另一个(调试或测试)实现来切换这个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();
}
}
Run Code Online (Sandbox Code Playgroud)
现在出现的问题是OkHttpClient不再被注入.当然我可以改变模块以接受参数OkHttpClient,但我不认为这是建议的方法.有没有理由为什么MainPresenterImpl没有正确注入?
与构造函数注入不同,方法@Inject中构造的依赖项的带注释字段@Provides无法自动注入。能够注入字段需要一个在其模块中提供字段类型的组件,而在提供者方法本身中,这样的实现不可用。
当presenter字段被注入时MainActivity,所发生的只是调用提供者方法并将presenter其设置为其返回值。在您的示例中,无参数构造函数不执行初始化,提供程序方法也不执行初始化,因此不会发生初始化。
然而,提供者方法确实可以通过其参数访问模块中提供的其他类型的实例。我认为在提供者方法中使用参数实际上是“注入”所提供类型的依赖项的建议(甚至是唯一)方法,因为它明确地将它们指示为模块内的依赖项,这允许 Dagger 在编译时抛出错误-如果他们不满意的话。
它当前不抛出错误的原因是因为如果并且不是注入目标的某处,MainPresenterImpl 则可以满足其OkHttpClient依赖性。Dagger 无法为接口类型创建成员注入方法,因为作为接口,它不能具有可注入字段,并且它不会自动注入实现类型的字段,因为它只是提供提供者方法返回。MainPresenterImplMainPresenter
您可以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);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7943 次 |
| 最近记录: |