为什么 Dagger2 要求我提供组件不应提供的内容?

Why is Dagger2 asking me to provide something that the component is not supposed to provide?

我正在尝试学习 Dagger2。就在我以为我明白了的时候,我似乎被卡住了。我的应用程序有两个组件, ApplicationComponent (singleton) 和 StripeComponent (1:1 activity) ,为了可读性,它们继承了一个空接口。

然后它有两个模块,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 提供的其中一个对象是 Navigator,我相当确定它的工作方式是相当正确的:

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

这是一个非常简单的 class,几乎什么都没有:

@Singleton public class Navigator

然后当我生成代码时,会从 StripeModule 生成一个额外的供应工厂 - StripeModule_ProvideNavigatorFactory。然后编译器抱怨说我没有提供它——这是真的,而且是故意的。它应该仅由应用程序组件提供。问题是,为什么会生成这个工厂呢?为什么 Dagger2 不理解 StripeModule 不应该提供导航器?

假设你有一个 StripeActivity class 使用 StripeComponent 来注入自己,那么你可能会遇到这样的场景

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 {
}

编辑:对于基础 class 注入,您需要手动注入 superclass 和 subclass,并且您需要同时指定 superclass 和组件中的 subclass 。在这种情况下,它会像这样工作。

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

您没有包括确切的错误,或者实际上取决于 Navigator 的代码。

但我假设依赖于 Navigator 的 class 是从 StripeModule 或安装到 StripeComponent 中的另一个模块提供的。

StripeComponentApplicationComponent 必须以某种方式相关,以便 StripeComponent 中的绑定使用 ApplicationComponent.

提供的绑定

您可以使用 component dependencies or subcomponents 来关联它们。

如果您使用子组件,您会将 StripeComponent 设为 ApplicationComponent 的子组件,这意味着它可以使用 ApplicationComponent 中安装的模块中的任何绑定,包括Navigator.

如果你想使用组件依赖,你可以让 StripeComponent 依赖于 ApplicationComponent,并且你可以添加一个方法 Navigator navigator()ApplicationComponentStripeComponent 中的绑定可以依赖于它所依赖的组件上的方法返回的任何类型。