Dagger2不能一直解决依赖问题

时间:2017-10-14 23:34:51

标签: java android dependency-injection dagger-2

我有一个注入Presenter的MainActivity,presenter对象注入了交互器,而者intector对象注入了APIHelper。 MainModule中有presenter,interactor和APIHelper的所有提供者。

 @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实现中,我有像:

这样的交互器
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();
    }

我的交互器实现类有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();
}

但是只有Presenter对象在MainActivity中创建,演示者中的所有其他对象包括interactor,APIHelper都是null。根据dagger,它应该解析所有依赖项。

2 个答案:

答案 0 :(得分:0)

更改MainPresenterImpl& ListingInteractorImpl构造函数在@Inject之后跟随并在它们之前:


    @Inject
    public MainPresenterImpl(MainActivity activity, ListingInteractor interactor) {...}

    @Inject
    public ListingInteractorImpl(Context context, APIHelper helper) {...}

然后在你的模块实现中:


    @Provides
    @Singleton
    public MainViewPresenter providesMainPresenter(ListingInteractor interactor){
        return new MainPresenterImpl(activity, interactor);
    }

    @Provides
    @Singleton
    ListingInteractor providesInteractor(APIHelper helper){
        return new ListingInteractorImpl(activity, helper);
    }


答案 1 :(得分:0)

匕首不是魔法。除非你告诉它,否则它不会在任何地方神奇地插入对象。

public class MainPresenterImpl implements MainViewPresenter {
  // ... other fields ...
  @Inject
  ListingInteractor interactor;

  public MainPresenterImpl(MainActivity activity) {
    this.context = activity;
    this.mainView = activity;
  }
}

匕首这......没什么。您为场注入标记了一些字段(ListingInteractor),但除非您手动调用组件以注入对象,否则不会发生任何事情。应该为活动和片段保留字段注入,您不能在构造函数中添加参数,而不是为普通类添加。

@Provides
@Singleton
MainViewPresenter providesMainPresenter(){
  return new MainPresenterImpl(activity);
}

不要让Dagger为你创建MainPresenterImpl,而是自己拨打new MainPresenterImpl(),只传递活动。由于没有MainPresenterImpl.interactor的来电,因此会null。您没有使用现场注入,您自己调用构造函数而您没有分配字段。
应该为需要进一步设置的对象保留在模块中手动创建对象,例如RetrofitOkHttp及其构建器。

如果您希望设置字段,可以使用字段注入并使用Component注册对象(那些inject(FieldInjectableClass clazz)方法)并在代码中撒component.inject(myObject),这将是非常糟糕的这个想法,因为你最终写了很多你不需要的样板。

更合理的方法是将依赖项移动到它们所属的构造函数。

public MainPresenterImpl(MainActivity activity, ListingInteractor interactor) { /* ... */ }

如果您对另一个类有依赖关系,为什么不这样声明呢?但是这仍然留下了你自己创造对象的样板,而不是让Dagger完成它的工作。

这就是为什么你应该使用 构造函数注入 的原因。顾名思义,它是关于构造函数的。只需添加@Inject注释:

@Inject // marked for constructor injection!
public MainPresenterImpl(MainActivity activity, ListingInteractor interactor) { /* ... */ }

现在Dagger知道你的班级的这个入口点并且可以创建它

让dagger处理事情你可以将@Singleton范围添加到类本身(注释类,而不是构造函数),只删除它的@Provides方法(不需要提供)模块中的方法,用于不需要进一步设置的对象),但由于您将实现绑定到接口,您仍需要指定要绑定到接口的类。

@Provides
@Singleton
MainViewPresenter providesMainPresenter(MainPresenterImpl implementation){
  return implementation;
}

由于Dagger可以使用构造函数注入创建MainPresenterImpl,因此您可以返回接口的实现,并且在构造函数签名发生更改时无需更新任何代码,因为Dagger将相应地调整类实例化。

如何使用构造函数注入并将实现绑定到接口。如上所述,我建议高度阅读基础知识。确保你了解Dagger的作用及其运作方式。请务必了解字段和构造函数注入之间的区别,或何时使用模块。

你现在投入学习Dagger的时间意味着更少的调试和错误。

如果你的模块是抽象的或接口,你也可以使用@Binds方法,Dagger只会生成上面的样板代码。

@Binds
@Singleton
MainViewPresenter providesMainPresenter(MainPresenterImpl implementation);