title: Different ViewModel instances from the same Component
body: <p>I have an Activity with a <code>ViewPager</code> that displays the same data either in a mapview (page 0) or in a list (page 1). There is some filtering happening, so I thought this filtering could be applied in the activity (which contains the views) and fed to the <code>ViewModel</code>, which via <code>LiveData</code> would update both <code>Fragments</code> (mapview and list)</p>
  
  <p>The theory sounds good but when I got to implement it, my component is always injecting new instances for the activity and both fragments. I found by printing the following lines:</p>
  
  <pre><code>05-31 13:36:16.832 16091-16091/W/DashboardActivity: Hello com.myapp.sample.ui.dashboard.DashboardViewModel@b8bb537 from com.myapp.sample.ui.dashboard.DashboardActivity@899a9f6
  05-31 13:36:17.133 16091-16091/W/MyPicksMapFragment: Hello com.myapp.sample.ui.dashboard.DashboardViewModel@59e2119 from MapFragment{72070f4 #1 id=0x7f090137 android:switcher:2131296567:0}
  05-31 13:36:18.139 16091-16091/W/MyPicksListFragment: Hello com.myapp.sample.ui.dashboard.DashboardViewModel@58a33fb from ListFragment{2be0446 #2 id=0x7f090137 android:switcher:2131296567:1}
  </code></pre>
  
  <p>This line proves its the same <code>Component</code>:</p>
  
  <pre><code>05-31 13:47:49.509 18411-18411/com.myapp.sample.dev.debug E/DashboardActivity: Saying hello from component com.myapp.sample.di.application.DaggerApplicationComponent$ControllerComponentImpl@4ccc864 within com.myapp.sample.ui.dashboard.DashboardActivity@57a81f7
  05-31 13:47:50.350 18411-18411/com.myapp.sample.dev.debug E/MyPicksMapFragment: Saying hello from component com.myapp.sample.di.application.DaggerApplicationComponent$ControllerComponentImpl@4ccc864 within MyPicksMapFragment{3443332 #1 id=0x7f090137 android:switcher:2131296567:0}
  05-31 13:47:51.194 18411-18411/com.myapp.sample.dev.debug E/MyPicksListFragment: Saying hello from component com.myapp.sample.di.application.DaggerApplicationComponent$ControllerComponentImpl@4ccc864 within MyPicksListFragment{e520996 #2 id=0x7f090137 android:switcher:2131296567:1}
  </code></pre>
  
  <p>This is my activity:</p>
  
  <pre><code>class DashboardActivity : BaseActivity&lt;DashboardViewModel&gt;() {
  
  
           override fun inject() {
               Timber.e("Saying hello from component $component within $this")
               component.inject(this)
           }
     }
  </code></pre>
  
  <p>Base Activity:</p>
  
  <pre><code>abstract class BaseActivity&lt;E : ViewModel&gt; : AppCompatActivity() {
  
   val component by lazy { (application as SoulpicksApp)
                       .applicationComponent
                       .plus(
                               ControllerModule(this)
                       )
               }
  
  
      @Inject
      protected lateinit var viewModel: E
  
      }
  
      @CallSuper
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
  
         inject()
    }
  </code></pre>
  
  <p>One of the fragments:</p>
  
  <pre><code>  class MyPicksListFragment : BaseFragment&lt;DashboardViewModel&gt;() {
      override fun inject() {
              var component = (activity as DashboardActivity).component
              Timber.e("Saying hello from component $component within $this")
              component.inject(this)
          }
  
    }
  </code></pre>
  
  <p>Base Fragment:</p>
  
  <pre><code>  abstract class BaseFragment&lt;E : ViewModel&gt; : Fragment() {
  
      @Inject
      protected lateinit var viewModel: E
  
      @CallSuper
      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
          super.onViewCreated(view, savedInstanceState)
          inject()
      }
  
  
  
    }
  </code></pre>
  
  <p>Application Component:</p>
  
  <pre><code>@Module(includes = [ViewModelModule::class])
  class ApplicationModule(val application: Application) {
  (...)
  }
  </code></pre>
  
  <p>ViewModelFactory:</p>
  
  <pre><code>class ViewModelFactory @Inject constructor(
          private val viewModels: MutableMap&lt;Class&lt;out ViewModel&gt;, Provider&lt;ViewModel&gt;&gt;
  ) : ViewModelProvider.Factory {
  
  
      override fun &lt;T : ViewModel?&gt; create(modelClass: Class&lt;T&gt;): T = viewModels[modelClass]?.get() as T
  }
  
  @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
  @kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
  @MapKey
  internal annotation class ViewModelKey(val value: KClass&lt;out ViewModel&gt;)
  </code></pre>
  
  <p>ViewModelModule:</p>
  
  <pre><code>@Module
  abstract class ViewModelModule {
  
   @Binds
      internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
  }
  
      @Binds
      @IntoMap
      @ViewModelKey(DashboardViewModel::class)
      internal abstract fun dashboardViewModel(viewModel: DashboardViewModel): ViewModel
  
  }
  </code></pre>
  
  <p>Controller Component:</p>
  
  <pre><code>@Module(includes = [ViewContainerModule::class])
  class ControllerModule(val activity: FragmentActivity) {
  
      @Provides
      @ControllerScope
      fun context(): Context = activity
  
      @Provides
      @ControllerScope
      fun activity() = activity
  
      @Provides
      @ControllerScope
      fun layoutInflater() = activity.layoutInflater
  
      @Provides
      @ControllerScope
      fun fragmentManager(): android.support.v4.app.FragmentManager = activity.supportFragmentManager
  
      @Provides
      @ControllerScope
      fun smsAuthManager(context: Context) = SmsAuthManager(context)
  
  
      @Provides
      @ControllerScope
      fun provideConnectivityManager(context: Context): ConnectivityManager =
              context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
  
      @Provides
      @ControllerScope
      fun provideNetworkInteractor(networkInteractor: NetworkInteractorImpl): NetworkInteractor = networkInteractor
  
      @Provides
      @ControllerScope
      fun provideLocationManager(context: Context): RxLocationManager = RxLocationManagerImpl(context)
  
      @Provides
      @ControllerScope
      fun provideNavigationController(activity: FragmentActivity) = NavigationController(activity)
  
  
  }
  </code></pre>