title: Submodules with Dagger and AndroidInjectors
body: <p>I have been Dagger with the pre Android Injector style for a while, and have now decided to try the new methods. Til now, I was basically declaring on <code>AppComponent</code> like this: </p>
  
  <pre><code>@Singleton
  @Component(
          modules = [ApplicationModule::class,
              NetModule::class,
              ApiModule::class,
              AnalyticsModule::class,
              DbModule::class,
              RepositoryModule::class,
              InteractorModule::class]
  )
  interface ApplicationComponent {
      fun inject(app: MyApp)
      fun plus(controllerModule: ControllerModule): ControllerComponent
  }
  </code></pre>
  
  <p>Then I would inject my <code>Activities</code>/<code>Fragments</code>/<code>Services</code>/<code>Dialogs</code> like this:</p>
  
  <pre><code>class MyActivity : AppCompatActivity() {
  ...
      val component by lazy {
              (application as MyApp)
                      .applicationComponent
                      .plus(
                              ControllerModule(this)
                      )
          }
  
      override fun inject() {
              component.inject(this)
          }
  ...
  }
  </code></pre>
  
  <p>Basically I had one top level app component with app-traversal modules, then an activity level component (<code>ControllerComponent</code>) with per-activity instances, common to all activities.</p>
  
  <p>Now that I switched to the new methods, I create my component like so:</p>
  
  <pre><code>@Singleton
  @Component(
          modules = [
              AndroidSupportInjectionModule::class,
              AppModule::class,
              NetModule::class,
              ApiModule::class,
              AnalyticsModule::class,
              DbModule::class,
              RepositoryModule::class,
              InteractorModule::class
          ]
  )
  interface AppComponent : AndroidInjector&lt;SoulpicksApp&gt; {
  
      @Component.Builder
      interface Builder {
          fun build(): AppComponent
          @BindsInstance
          fun application(application: SoulpicksApp): Builder
      }
  
  }
  </code></pre>
  
  <p>Make my app extend <code>DaggerApplication</code>:</p>
  
  <pre><code>open class MyApp : DaggerApplication() {
  
  
      override fun applicationInjector(): AndroidInjector&lt;out DaggerApplication&gt; = DaggerAppComponent.builder().application(this).build()
  
  }
  </code></pre>
  
  <p>And my <code>Activities</code>/<code>Fragments</code> extend <code>DaggerAppCompatActivty</code>/<code>DaggerFragment</code> respectively:</p>
  
  <pre><code>class MyActivity : DaggerAppCompatActivity() {
  
  ...
  }
  </code></pre>
  
  <p>I understand this should automatically wire up all the activities dependencies, provided Dagger is properly set up. However I havent declared my <code>ControllerModule</code>/<code>Component</code> so of course when running my app I get:</p>
  
  <pre><code>e: /Users/user/dev/my-android/app/build/generated/source/kapt/devDebug/com/myapp/android/di/activity/ActivityBinder_ContributesMyActivity.java:28: error: @Subcomponent.Builder is missing setters for required modules or subcomponents: [com.myapp.android.di.controller.ControllerModule]
  </code></pre>
  
  <p>I understand previously I was creating this component on each <code>Activity</code> by using the plus() method and injecting explicitly (which is what I am trying to avoid here), how can I do that now?</p>
  
  <p>Also, I have some <code>BottomSheetDialogFragments</code> and <code>JobServiceIntents</code> in my app, and theres no equivalent <code>DaggerBottomSheedDialogFragments</code>/<code>DaggerJobServiceIntents</code> to extend from, how can I work around that?</p>
  
  <p>ControllerModule:</p>
  
  <pre><code>@Module
  class ControllerModule(val activity: androidx.fragment.app.FragmentActivity) {
  
      @Provides
      @ControllerScope
      fun context(): Context = activity
  
      @Provides
      @ControllerScope
      fun activity() = activity
  
      @Provides
      @ControllerScope
      fun layoutInflater() = activity.layoutInflater
  
      @Provides
      @ControllerScope
      fun fragmentManager(): androidx.fragment.app.FragmentManager = activity.supportFragmentManager
  
      @Provides
      @ControllerScope
      fun provideNavigationController(activity: androidx.fragment.app.FragmentActivity, analyticsManager: AnalyticsCompositeManager) = NavigationController(activity, analyticsManager)
  
      @Provides
      @ControllerScope
      fun providePackageUtils(activity: androidx.fragment.app.FragmentActivity) : PackageUtils = PackageUtilsImpl(activity)
  }
  </code></pre>
  
  <p>Changes after @luis_cortes answer:</p>
  
  <p>package io.soulpicks.android.di.activity</p>
  
  <pre><code>@Module
  abstract class ActivityBinder {
  
      @ControllerScope
      @ContributesAndroidInjector(modules = [ControllerModule::class])
      abstract fun constributesSplashActivity(): SplashActivity
  
      @ControllerScope
      @ContributesAndroidInjector(modules = [ControllerModule::class])
      abstract fun contributesDashboardActivity(): DashboardActivity
  
      ....
  
  
  }
  </code></pre>
  
  <p>ControllerModule:</p>
  
  <pre><code>@Module(includes = [ViewContainerModule::class])
  class ControllerModule {
  
  
      @Provides
      @ControllerScope
      fun context(activity: DaggerAppCompatActivity): Context = activity.applicationContext
  
      @Provides
      @ControllerScope
      fun layoutInflater(activity: DaggerAppCompatActivity) : LayoutInflater = activity.layoutInflater
  
      @Provides
      @ControllerScope
      fun fragmentManager(activity: DaggerAppCompatActivity): FragmentManager = activity.supportFragmentManager
  
      @Provides
      @ControllerScope
      fun navigationController(activity: DaggerAppCompatActivity, analyticsManager: AnalyticsCompositeManager): NavigationController = NavigationController(activity, analyticsManager)
  
      @Provides
      @ControllerScope
      fun providePackageUtils(activity: DaggerAppCompatActivity): PackageUtils = PackageUtilsImpl(activity)
  }
  </code></pre>
  
  <p>Error:</p>
  
  <pre><code>e: /Users/kelmer/dev/myapp-android/app/build/tmp/kapt3/stubs/devDebug/io/myapp/android/di/application/AppComponent.java:8: error: [Dagger/MissingBinding] com.myapp.android.managers.PackageUtils cannot be provided without an @Provides-annotated method.
  public abstract interface AppComponent extends dagger.android.AndroidInjector&lt;com.myapp.android.MyApp&gt; {
                  ^
        com.myapp.android.managers.PackageUtils is injected at
            com.myapp.android.ui.invite.SendInviteViewModel(packageUtils, …)
        com.myapp.android.ui.invite.SendInviteViewModel is injected at
            com.myapp.android.di.viewmodel.ViewModelModule.sendInviteViewModel$app_devDebug(sendInviteViewModel)
        java.util.Map&lt;java.lang.Class&lt;? extends androidx.lifecycle.ViewModel&gt;,javax.inject.Provider&lt;androidx.lifecycle.ViewModel&gt;&gt; is injected at
            com.myapp.android.di.viewmodel.MyappViewModelFactory(viewModels)
        com.myapp.android.di.viewmodel.MyappViewModelFactory is injected at
            com.myapp.android.di.viewmodel.ViewModelModule.bindViewModelFactory$app_devDebug(factoryMyapp)
        androidx.lifecycle.ViewModelProvider.Factory is injected at
            com.myapp.android.base.BaseActivity.viewModelFactory
        com.myapp.android.ui.splash.SplashActivity is injected at
            dagger.android.AndroidInjector.inject(T) [com.myapp.android.di.application.AppComponent → com.myapp.android.di.activity.ActivityBinder_ConstributesSplashActivity.SplashActivitySubcomponent]
    It is also requested at:
        com.myapp.android.ui.dashboard.friends.contact.ContactSyncViewModel(…, packageUtils, …)
        com.myapp.android.views.appchoosedialog.AppChooserViewModel(packageUtils)
    The following other entry points also depend on it:
        dagger.android.AndroidInjector.inject(T) [com.myapp.android.di.application.AppComponent → com.myapp.android.di.activity.ActivityBinder_ContributesDashboardActivity.DashboardActivitySubcomponent]
  </code></pre>
  
  <p><a href="https://github.com/kelmer44/mvvm-base" rel="nofollow noreferrer">https://github.com/kelmer44/mvvm-base</a></p>
  
  <p>branch <code>master</code> is current implementation (no dagger-android)
  branch <code>chore/dagger-rework</code> is my attempt</p>