2017-10-14 28 views
0

我有一个注入Presenter的MainActivity,Presenter对象注入交互器和交互器对象注入APIHelper。 MainModule中有演示者,交互者和APIHelper的所有提供者。Dagger2不能一直解决依赖关系

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

在我的演示实现我有相互作用分子,如:

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创建演示者的其他所有对象,包括交互器,APIHelper被null.According到匕首它应该可以解决所有的依赖关系。

+0

您是否在Dagger组件中注入了演示者?否则我不认为它会工作。一般来说,这个活动有一个@Inject Presenter p;主持人有迭代器或任何你想要注入的东西,注入他的构造函数中。因此,演示者构造函数将是MainPresenterImpl(activity,iterator)。并且Dagger会知道你在模块中提供了迭代器的内容(不知道是否清楚) – Eselfar

+0

看起来你缺少一些关于如何使用Dagger以及它如何工作的基础知识。我建议您再次阅读Dagger 2用户指南或其他一些教程,并确保您了解如何提供或注入依赖 –

+0

@Eselfar我已添加组件接口的代码。我在组件中有一个主持人,它正在MainActivity中初始化,但是我在主持人内部注入的对象没有像交互者和交互者中的交互者和apihelper一样初始化 – ozmank

回答

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

与其让匕首为你创造MainPresenterImpl的,你打个电话给自己,只有通过在活动。由于没有致电MainPresenterImpl.interactor,它将是null。你不使用字段注入,你自己调用构造函数,而且你没有分配字段。
手动创建模块中的对象应保留给需要进一步设置的对象,例如RetrofitOkHttp及其制造商。

如果您希望您的字段进行设置,你可以使用字段注入,并与组件注册你的对象(这些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) { /* ... */ } 

现在匕首知道这个切入点,以您的类,并可以创建它

为了让匕首处理的事情,你可以在@Singleton范围添加到类本身(注释类,而不是构造函数),只是删除它@Provides方法(也没有必要提供模块的方法的对象,唐不需要进一步的设置),但是因为你将一个实现绑定到一个接口,所以你仍然需要指定你想绑定到该接口的类。

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

由于匕首可以创建MainPresenterImpl与构造函数注入你可以返回实现你的接口,并且没有必要的情况下更新任何代码构造函数签名的变化,匕首只会相应地调整类的实例化。

这就是如何使用构造函数注入并将实现绑定到接口。如前所述,我建议高度阅读基础知识。确保你了解匕首的作用和工作原理。一定要知道字段和构造函数注入的区别,或者何时使用模块。

你现在投入学习匕首的时间意味着稍后的调试和错误会少得多。


在你的模块是抽象或接口的情况下,你也可以使用@Binds方法,其中匕首将只产生上面的样板代码。

@Binds 
@Singleton 
MainViewPresenter providesMainPresenter(MainPresenterImpl implementation); 
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); 
    }