2015-12-09 41 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中的绑定可以依赖于方法在其所依赖的组件上返回的任何类型。

相关问题