Dagger2没有完全解决依赖问题 [英] Dagger2 not resolving dependency all the way

查看:138
本文介绍了Dagger2没有完全解决依赖问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a MainActivity which injects Presenter, presenter object injects interactor and interactor object injects APIHelper. All the providers of presenter, interactor and APIHelper are there in 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如:

I have injected the component in the MainActivity like:

DaggerMainActivityComponent.builder()
                .mainActivityModule(new MainActivityModule(MainActivity.this))
                .build().inject(this);

在我的Presenter实现中,我有类似的交互器:

In my Presenter implementation I have interactor like:

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助手,其构造函数需要上下文

My interactor implementation class has API helper whose constructor needs context

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中创建,包括交互器在内的所有其他对象,APIHelper为null。根据匕首,它应解决所有依赖关系。

but only presenter object is created in the MainActivity all other objects in presenter including interactor, APIHelper are null.According to dagger it should resolve all dependencies.

推荐答案

Dagger不是魔法。它不会神奇地在任何地方插入对象,除非你告诉它这样做。

Dagger is not magic. It will not magically insert objects wherever you want unless you tell it to do so.

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

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

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

To Dagger this is...nothing. You marked some field (ListingInteractor) for field injection, but unless you manually call a component to inject your object nothing will happen. Field injection should be reserved for Activities and Fragments where you can't add arguments to the constructor, not for your average classes.

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

而不是让Dagger创建 MainPresenterImpl 对你来说,你自己打电话给新的MainPresenterImpl(),只传递活动。由于没有调用 MainPresenterImpl.interactor ,因此它将是 null 。你没有使用字段注入,你自己调用构造函数而你没有分配字段。

手动创建模块中的对象应该保留给需要进一步设置的对象,比如改造 OkHttp 及其建造者。

Instead of letting Dagger create MainPresenterImpl for you, you make a call to new MainPresenterImpl() yourself, only passing in the Activity. Since there is no call to MainPresenterImpl.interactor, it will be null. You're not using field injection, you're calling the constructor yourself and you're not assigning the field.
Manually creating objects in modules should be reserved for objects that require further setup, like Retrofit or OkHttp with their builders.

如果你想要你的田地要设置,你可以使用字段注入并使用Component注册你的对象(那些注入(FieldInjectableClass clazz)方法)并撒上 component.inject( myObject)在整个代码中,这将是一个非常糟糕的主意,因为你最终会编写很多你不需要的样板文件。

If you want your fields to be set, you could use field injection and register your objects with the Component (those inject(FieldInjectableClass clazz) methods) and sprinkle component.inject(myObject) throughout your code, which would be a really bad idea because you'd end up writing a lot of boilerplate that you don't need.

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

The more reasonable way is to move your dependencies to the constructor, where they belong.

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

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

If you have a dependency on another class, why not declare it as such? But this still leaves the boilerplate of you creating the object yourself, instead of letting Dagger do its job.

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

That's why you should use Constructor Injection. As the name suggests, it's about the constructor. Just add the @Inject annotation:

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

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

Now Dagger knows about this entry point to your class and can create it.

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

To let dagger handle things you could add the @Singleton scope to the class itself (annotate the class, not the constructor) and just delete the @Provides method for it (there is no need for provides methods in modules for objects that don't need further setup), but since you're binding an Implementation to an Interface you still need to specify which class you want to bind to the interface.

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

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

Since Dagger can create MainPresenterImpl with constructor injection you can return the implementation for your interface, and there is no need to update any code in case the constructor signature changes, as Dagger will just adapt the class instantiation accordingly.

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

That's how to use constructor injection and bind implemenations to interfaces. And as mentioned, I recommend highly to read up on the basics. Make sure you understand what Dagger does and how it works. Be sure to know the difference between field and constructor injection, or when to use modules.

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

The time you invest now in learning Dagger will mean much less debugging and errors later on.

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

In case that your module is abstract or an interface, you can also make use of the @Binds method, where Dagger will just generate the boilerplate code above.

@Binds
@Singleton
MainViewPresenter providesMainPresenter(MainPresenterImpl implementation);

这篇关于Dagger2没有完全解决依赖问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆