使用ContributesAndroidInjector提供活动

时间:2018-06-20 05:59:02

标签: java android dependency-injection dagger-2

我在向需要此对象的依赖对象提供Settings -> Permalinks对象时遇到问题。

我使用Dagger 2.13进行了非常标准的设置,如下所示:

Activity

AppComponent.java

@Singleton @Component(modules = { AndroidInjectionModule.class, AppModule.class, ActivityModule.class }) public interface AppComponent extends AndroidInjector<Appname> { @Component.Builder interface Builder { @BindsInstance Builder application(Appname appname); AppComponent build(); } void inject(Appname appname); }

ActivityModule.java

@Module abstract public class ActivityModule { @ContributesAndroidInjector(modules = {MainActivityModule.class, MainActivityFragmentsModule.class}) abstract MainActivity contributeMainActivity(); }

MainActivityModule.java

@Module public class MainActivityModule { @Provides @Singleton static Billing provideBilling(Context context) { return new Billing(context); } @Provides @Singleton static ActivityCheckout provideActivityCheckout(MainActivity activity, Billing billing) { return ActivityCheckout.forActivity(activity, billing); } }

MainActivityFragmentsModule.java

当我尝试在@Module abstract public class MainActivityFragmentsModule { @ContributesAndroidInjector abstract WelcomeFragment contributeWelcomeFragment(); } 中使用ActivityCheckout时,出现错误,提示无法提供此依赖项:

WelcomeFragment

似乎没有提供该活动,但我不知道为什么。我试图按照其中一项设置相同的教程进行操作,并且可以注入Error:(20, 8) error: [dagger.android.AndroidInjector.inject(T)] org.solovyev.android.checkout.ActivityCheckout cannot be provided without an @Inject constructor or from an @Provides-annotated method.对象。

我正在使用ActivityDaggerApplicationDaggerAppCompatActivity

1 个答案:

答案 0 :(得分:3)

尽管我不确定如何/为什么会显示您所显示的错误,但是您在@Singleton范围内错误地注册了活动范围的内容。请注意,您发布的错误消息抱怨没有提供ActivityCheckout。如果无法提供您的活动,则可能会找到一条有关缺少MainActivity的错误消息。

我的直觉是,您的编译中存在多个错误,但您仅发布了最后一个错误,而较早的错误表明您无法将@Singleton绑定安装到@ContributesAndroidInjector默认创建的不受作用域的子组件中。因此,Dagger会忽略该@Provides方法,并且会收到错误消息。

@Provides
@Singleton  // BAD: If this is Singleton, it will outlive and leak MainActivity.
            // Dagger will complain about mismatched scopes, but it's right:
            // It doesn't make sense for ActivityCheckout to be @Singleton.
static ActivityCheckout provideActivityCheckout(
    MainActivity activity, Billing billing) {
  return ActivityCheckout.forActivity(activity, billing);
}

相反,创建一个特定于活动的范围,该范围指示每个活动都有自己的活动。

@Retention(RetentionPolicy.RUNTIME)    // Not used at runtime, but JSR-330
@Scope                                 // requires that @Scopes are kept at RUNTIME.
public @interface ActivityScope {}     // PerActivity is also a good name.

现在用它标记@ContributesAndroidInjector,以便您生成的子组件具有该范围:

@ContributesAndroidInjector(
    modules = {MainActivityModule.class, MainActivityFragmentsModule.class})
@ActivityScope
abstract MainActivity contributeMainActivity();

您的绑定也是如此,因此它们与活动组件的生命周期相匹配:

@Module public class MainActivityModule {
  // I'm assuming this is actually activity scoped, but if it's truly singleton,
  // leave it @Singleton and move it to AppModule.
  @Provides
  @ActivityScope
  static Billing provideBilling(Context context) {
    return new Billing(context);
  }

  @Provides
  @ActivityScope
  static ActivityCheckout provideActivityCheckout(
      MainActivity activity, Billing billing) {
    return ActivityCheckout.forActivity(activity, billing);
  }
}