为什么 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
中的另一个模块提供的。
StripeComponent
和 ApplicationComponent
必须以某种方式相关,以便 StripeComponent
中的绑定使用 ApplicationComponent
.
提供的绑定
您可以使用 component dependencies or subcomponents 来关联它们。
如果您使用子组件,您会将 StripeComponent
设为 ApplicationComponent
的子组件,这意味着它可以使用 ApplicationComponent
中安装的模块中的任何绑定,包括Navigator
.
如果你想使用组件依赖,你可以让 StripeComponent
依赖于 ApplicationComponent
,并且你可以添加一个方法 Navigator navigator()
到 ApplicationComponent
。 StripeComponent
中的绑定可以依赖于它所依赖的组件上的方法返回的任何类型。
我正在尝试学习 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
中的另一个模块提供的。
StripeComponent
和 ApplicationComponent
必须以某种方式相关,以便 StripeComponent
中的绑定使用 ApplicationComponent
.
您可以使用 component dependencies or subcomponents 来关联它们。
如果您使用子组件,您会将 StripeComponent
设为 ApplicationComponent
的子组件,这意味着它可以使用 ApplicationComponent
中安装的模块中的任何绑定,包括Navigator
.
如果你想使用组件依赖,你可以让 StripeComponent
依赖于 ApplicationComponent
,并且你可以添加一个方法 Navigator navigator()
到 ApplicationComponent
。 StripeComponent
中的绑定可以依赖于它所依赖的组件上的方法返回的任何类型。