Dagger2 没有完全解决依赖关系

2024-01-08

我有一个 MainActivity,它注入 Presenter,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)均为 null。根据 dagger,它应该解析所有依赖项。


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

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。您没有使用字段注入,您自己调用构造函数并且没有分配字段。
在模块中手动创建对象应该保留给需要进一步设置的对象,例如Retrofit or OkHttp和他们的建设者。

如果您希望设置字段,您可以使用字段注入并向组件注册您的对象(那些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);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Dagger2 没有完全解决依赖关系 的相关文章

随机推荐