java Dagger2没有完全解决依赖关系
我有一个MainActivity,它注入Presenter,Presenter对象注入interactor,interactor对象注入APIHelper。演示者、交互者和APIHelper的所有提供者都在MainModule中
@Module
public class MainActivityModule {
private final MainActivity activity;
//Context context;
public MainActivityModule (MainActivity activity) {
this.activity = activity;
}
@Provides
@Singleton
public MainViewPresenter providesMainPresenter(){
return new MainPresenterImpl(activity);
}
@Provides
@Singleton
ListingInteractor providesInteractor( ){
return new ListingInteractorImpl(activity);
}
@Provides
@Singleton
ApiHelper providesAPI( ){
return new ApiHelper(activity);
}
}
我已在MainActivity中注入组件,如:
DaggerMainActivityComponent.builder()
.mainActivityModule(new MainActivityModule(MainActivity.this))
.build().inject(this);
在我的Presenter实现中,我有一个类似interactor的:
public class MainPresenterImpl implements MainViewPresenter {
Context context;
private MainView mainView;
// @Inject
ListingInteractor interactor; //here i get null interactor
MyScrollListener scrollListener;
public MainPresenterImpl(MainActivity activity) {
this.context = activity;
this.mainView = activity;
}
@Override
public void getCatFacts() {
interactor.getFacts();
}
我的interactor实现类具有API帮助器,其构造函数需要上下文
public class ListingInteractorImpl implements ListingInteractor{
private Context context;
@Inject
private APIHelper; // getting null APIHelper
public ListingInteractorImpl(Context context) {
this.context = context;
}
我的组件界面如下所示:
@Component(modules={MainActivityModule.class})
@Singleton
public interface MainActivityComponent {
void inject(MainActivity mainActivity);
/*void inject(MainPresenterImpl presenter);*/
MainViewPresenter getMainPresenter();
ListingInteractor getInteractor();
ApiHelper getHelper();
}
但仅在MainActivity中创建presenter对象presenter中的所有其他对象(包括interactor、APIHelper)均为空。根据dagger的说法,它应该解决所有依赖关系
# 1 楼答案
匕首不是魔法。它不会神奇地将对象插入到任何你想要的地方,除非你告诉它这样做
匕首这是。。。没有什么您将一些字段(
ListingInteractor
)标记为字段注入,但除非手动调用组件来注入对象,否则不会发生任何事情。字段注入应该为不能向构造函数添加参数的活动和片段保留,而不是为普通类保留与其让Dagger为您创建
MainPresenterImpl
,不如自己调用new MainPresenterImpl()
,只传递活动。因为没有对MainPresenterImpl.interactor
的调用,所以它将是null
。您没有使用字段注入,您自己调用构造函数,也没有分配字段在模块中手动创建对象应保留给需要进一步设置的对象,如
Retrofit
或OkHttp
及其构建器如果您想设置字段,可以使用字段注入,将对象注册到组件(那些
inject(FieldInjectableClass clazz)
方法)中,并在代码中散布component.inject(myObject)
,这将是一个非常糟糕的主意,因为您最终会编写大量不需要的样板文件更合理的方法是将依赖项移动到它们所属的构造函数
如果您依赖于另一个类,为什么不声明它呢?但这仍然留下了你自己创建对象的样板,而不是让Dagger完成它的工作
这就是为什么您应该使用构造函数注入。顾名思义,它是关于构造函数的。只需添加
@Inject
注释:现在Dagger知道你的类的这个入口点,并且可以创建它
要让dagger处理事情,您可以将
@Singleton
作用域添加到类本身(注释类,而不是构造函数),然后删除它的@Provides
方法(不需要在模块中为不需要进一步设置的对象提供方法),但是,由于要将实现绑定到接口,因此仍然需要指定要绑定到接口的类因为Dagger可以通过构造函数注入创建
MainPresenterImpl
,所以您可以返回接口的实现,并且在构造函数签名更改的情况下不需要更新任何代码,因为Dagger只会相应地调整类实例化这就是如何使用构造函数注入并将实现绑定到接口。如前所述,我强烈建议大家阅读基础知识。确保你们了解匕首的作用和工作原理。确保知道字段注入和构造函数注入之间的区别,或者何时使用模块
您现在在学习Dagger上投入的时间将意味着以后调试和错误将大大减少
如果您的模块是抽象的或接口,您也可以使用
@Binds
方法,Dagger将只生成上面的样板代码# 2 楼答案
更改
MainPresenterImpl
&ListingInteractorImpl
构造函数以@Inject
开头并跟随它们:然后在模块实现中: