2015-12-09 40 views
0

我在玩弄試圖學習Dagger2。就在我想我得到它時,我似乎陷入了困境。我的應用程序有兩個組件,ApplicationComponent(singleton)和StripeComponent(1:1 activity),爲了便於閱讀,它繼承了一個空的接口。爲什麼Dagger2要求我提供組件不應該提供的東西?

然後它有兩個模塊,ApplicationModule和StripeModule。

@Singleton @Component(modules = ApplicationModule.class) 
public interface ApplicationComponent extends AbstractComponent ... 

@PerActivity @Component(modules = { StripeModule.class }) public interface StripeComponent 
extends AbstractComponent ... 

@Module public class ApplicationModule 
@Module public class StripeModule 

一個ApplicationModule提供的是一個導航儀,我比它的方式相當肯定的對象是相當正確的:

@Provides @Singleton Navigator provideNavigator() { 
    return new Navigator(); 
} 

這是一個非常簡單的類幾乎沒有在它尚未:

@Singleton public class Navigator 

然後,當我生成的代碼,從StripeModule產生額外提供工廠 - StripeModule_ProvideNavigatorFactory。然後編譯器會聲明我沒有提供它 - 這是真的,而且是有意的。它應該僅由應用程序組件提供。問題是,爲什麼這個工廠正在生成呢?爲什麼Dagger2不明白StripeModule不應該提供導航器?

+1

您是否試圖從'@ Singleton'作用域組件繼承'Navigator'到您的'@ PerActivity'作用域?如果你通過'@Inject Navigator navigator'''注入'StripeActivity',通過'StripeComponent'',那麼你需要提供導航器。這就是爲什麼我問這是否是你想要做的。 – EpicPandaForce

+0

其實,只需要包含'StripeModule','ApplicationModule'和你試圖用這些組件之一注入的類(特別是如果它包含'@Inject Navigator navigator;') – EpicPandaForce

+0

啊,我只是然後,基於我認爲你想要的結果寫了一個答案。 – EpicPandaForce

回答

3

假設你有一個使用StripeComponent注入本身就是一個StripeActivity類,那麼你可能最終得到這樣一個

public class StripeActivity extends AppCompatActivity { 
    @Inject 
    Navigator navigator; 

    @Override 
    public void onCreate(Bundle saveInstanceState) { 
     super.onCreate(saveInstanceState); 
     CustomApplication application = (CustomApplication)getApplicationContext(); 
     StripeComponent stripeComponent = createComponent(application); 
     stripeComponent.inject(this); 
    } 

    protected StripeComponent createComponent(CustomApplication application) { 
     return DaggerStripeComponent.builder() 
       .applicationComponent(application.getApplicationComponent()) 
       .build(); 
    } 
} 

public class CustomApplication extends Application { 
    ApplicationComponent applicationComponent; 

    @Override 
    protected void onCreate() { 
     super.onCreate(); 
     applicationComponent = createApplicationComponent(); 
    } 

    protected ApplicationComponent createApplicationComponent() { 
     return DaggerApplicationComponent.create(); 
    } 

    public ApplicationComponent getApplicationComponent() { 
     return applicationComponent; 
    } 
} 

@Component(modules={ApplicationModule.class}) 
@Singleton 
public interface ApplicationComponent { 
    Navigator navigator(); 
} 

@Component(dependencies={ApplicationComponent.class}, modules={StripeModule.class}) 
@PerActivity 
public interface StripeComponent extends ApplicationComponent { 
    void inject(StripeActivity stripeActivity); 
} 

@Module 
public class ApplicationModule { 
    @Provides 
    @Singleton 
    Navigator navigator() { 
     return new Navigator(); 
    } 
} 

@Module 
public class StripeModule { 
    //@Provides 
    //@PerActivity 
    //... 
} 

@Scope 
@Retention(RUNTIME) 
public @interface PerActivity { 
} 

編輯方案:對於基礎類注射,你需要注入兩超和手動創建子類,並且需要在組件中指定超類和子類。在這種情況下,它會像這樣工作。

public abstract class BaseActivity extends AppCompatActivity { 
    @Inject 
    Navigator navigator; 

    @Override 
    public void onCreate(Bundle saveInstanceState) { 
     super.onCreate(saveInstanceState); 
     CustomApplication application = (CustomApplication)getApplicationContext(); 
     ApplicationComponent component = createComponentAndInjectSelf(application); 
     component.inject(this); 
    } 

    protected abstract ApplicationComponent createComponentAndInjectSelf(CustomApplication application); 
} 

public class StripeActivity extends BaseActivity { 
    @Override 
    public void onCreate(Bundle saveInstanceState) { 
     super.onCreate(saveInstanceState); 
    } 

    @Override 
    public StripeComponent createComponentAndInjectSelf(CustomApplication application) { 
     StripeComponent stripeComponent = DaggerStripeComponent.builder() 
      .applicationComponent(application.getApplicationComponent()) 
      .build(); 
     stripeComponent.inject(this); 
     return stripeComponent; 
    } 
} 

@Component(modules={ApplicationModule.class}) 
@Singleton 
public interface ApplicationComponent { 
    Navigator navigator(); 

    void inject(BaseActivity baseActivity); 
} 

@Component(dependencies={ApplicationComponent.class}, modules={StripeModule.class}) 
@PerActivity 
public interface StripeComponent extends ApplicationComponent { 
    void inject(StripeActivity stripeActivity); 
} 
+0

對不起,我正在回答你的評論,但我不得不離開。您的第一條評論完全正確:StripeActivity繼承了我用於全局依賴關係的抽象活動,這些活動由ApplicationModule提供。但是,從兩個模塊中提供導航器並不覺得是正確的,主要是因爲導航器不是ApplicationComponent提供的唯一依賴項,因爲它最終會導致大量重複的代碼。我猜你發佈的這些代碼是避免這些重複的正確方法,我明天會試一試。非常感謝! –

+0

基類注入很棘手,因爲您必須在超類和子類中調用注入,並且需要在組件中指定超類和子類,我將在編輯中添加它。 – EpicPandaForce

+1

好吧,現在驗證一下,非常感謝,很抱歉,我沒有時間。 –

0

您還沒有包括確切的錯誤或實際取決於Navigator的代碼。

但我會假設依賴於Navigator的類是從StripeModule或其他模塊安裝到StripeComponent中提供的。

StripeComponentApplicationComponent必須以某種方式,才能在StripeComponent使用由ApplicationComponent提供的綁定相關的綁定。

您可以使用component dependenciessubcomponents與它們相關聯。

如果使用子,你會做StripeComponentApplicationComponent子組件,這將意味着它可以安裝在ApplicationComponent模塊,包括一個用於Navigator使用任何綁定。

如果您要使用組件依賴關係,您將使StripeComponent取決於ApplicationComponent,並且您會將方法Navigator navigator()添加到ApplicationComponentStripeComponent中的綁定可以依賴於方法在其所依賴的組件上返回的任何類型。

相關問題