2017-10-14 36 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); 
    }