【问题标题】:Dagger2 not resolving dependency all the wayDagger2 没有完全解决依赖关系
【发布时间】:2017-10-17 06:18:22
【问题描述】:

我有一个注入 Presenter 的 MainActivity,presenter 对象注入交互器,交互器对象注入 APIHelper。所有 Presenter、Interactor 和 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 实现中,我有这样的交互器:

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();
}

但在 MainActivity 中只创建了 Presenter 对象,Presenter 中的所有其他对象,包括交互器、APIHelper 都是空的。根据 dagger 它应该解决所有依赖项。

【问题讨论】:

  • 你是否在 Dagger 组件中注入了演示者?否则我认为它不会起作用。通常活动有一个@Inject Presenter p;并且演示者具有迭代器或您想要注入的任何东西,注入到他的构造函数中。所以演示者构造函数将是 MainPresenterImpl(activity, iterator)。如果你在模块中提供了迭代器,Dagger 就会知道要注入什么(如果很清楚,不要知道)
  • 您似乎缺少有关如何使用 Dagger 及其工作原理的一些基础知识。我建议您再次阅读 Dagger 2 用户指南或其他一些教程,并确保您了解如何提供或注入依赖项
  • @Eselfar 我为组件接口添加了代码。我在组件中有演示者,它正在 MainActivity 中初始化,但是我在演示者中注入的对象没有像交互器中的交互器和 apihelper 那样被初始化
  • @DavidMedenjak 我已经添加了更多代码你能告诉我我在这里做错了什么吗,从概念上来说,模块有提供者,匕首搜索提供者来解决依赖关系。组件作为接口需要依赖的提供者和类。

标签: java android dependency-injection dagger-2


【解决方案1】:

匕首不是魔法。除非您告诉它这样做,否则它不会神奇地将对象插入到您想要的任何位置。

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

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

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

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

您无需让 Dagger 为您创建 MainPresenterImpl,而是自己调用 new MainPresenterImpl(),仅传入 Activity。由于没有对MainPresenterImpl.interactor 的调用,它将是null。您没有使用字段注入,而是自己调用构造函数并且没有分配字段。
在模块中手动创建对象应保留给需要进一步设置的对象,例如 RetrofitOkHttp 及其构建器。

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

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

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);

【讨论】:

    【解决方案2】:

    MainPresenterImplListingInteractorImpl 构造函数更改为跟随并在它们前面加上@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); }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-18
      • 1970-01-01
      • 1970-01-01
      • 2021-07-23
      • 2015-02-17
      • 2016-02-16
      • 2017-02-20
      相关资源
      最近更新 更多