title: How to use AssistedInject to pass dynamic value as a parameter to ViewModel when using Dagger2 in Android
body: <p>I am new to Dagger 2 in android. I am having trouble understanding how to inject <code>ViewModel</code> with dynamic value. So Far I have successfully injected ViewModel using dagger multi binding with pre-defined repository dependency. Here's my code.</p>
  <p><strong>ApplicationComponent</strong></p>
  <pre><code>@Singleton
  @Component(modules = [AppModule::class, SubComponentsModule::class, ViewModelFactoryModule::class])
  interface ApplicationComponent {
  
      @Component.Factory
      interface Factory {
          fun create(@BindsInstance applicationContext: Context): ApplicationComponent
      }
  
      fun activityComponent(): ActivitySubComponent.Factory
      fun fragmentComponent(): FragmentSubComponent.Factory
  
  }
  </code></pre>
  <p><strong>FragmentModule</strong></p>
  <pre><code>@Module
  abstract class FragmentModule {
  
      @Binds
      @IntoMap
      @ViewModelKey(WeatherViewModel::class)
      abstract fun bindWeatherView(weatherViewModel: WeatherViewModel) : ViewModel
  
  }
  </code></pre>
  <p><strong>ViewModelFactoryModule</strong></p>
  <pre><code>@Module
  class ViewModelFactoryModule {
  
      @Provides
      @Singleton
      fun viewModelFactory(providerMap: Map&lt;Class&lt;out ViewModel&gt;, Provider&lt;ViewModel&gt;&gt;): ViewModelProvider.Factory {
          return ViewModelFactory(providerMap)
      }
  }
  </code></pre>
  <p><strong>Application class</strong></p>
  <pre><code>class ThisApplication: Application(),InjectorProvider {
  
      override fun onCreate() {
          super.onCreate()
  
          Stetho.initializeWithDefaults(this)
      }
  
      override val component by lazy {
          DaggerApplicationComponent.factory().create(applicationContext)
      }
  
  }
  </code></pre>
  <p>I'm using <code>InjectorProvider</code> interface to get dagger to fragments and activity without having to cast every time.</p>
  <p><strong>InjectorProvider</strong></p>
  <pre><code>interface InjectorProvider {
    val component: ApplicationComponent
  }
  
  val Activity.injector get() = (application as InjectorProvider).component
  val Fragment.injector get() = (requireActivity().application as InjectorProvider).component
  </code></pre>
  <p>This is the simple <code>ViewModel</code> I used for testing <code>ViewModel</code> injection.</p>
  <p><strong>WeatherViewModel</strong></p>
  <pre><code>class WeatherViewModel @Inject constructor(val repository: WeatherRepository): ViewModel() {
  
      fun printMessage(){
          Log.d(&quot;WeatherViewModel&quot;,&quot;ViewModel binding is working&quot;)
          repository.printMessage()
      }
  
  }
  </code></pre>
  <p>Finally, I Injected this view model into a fragment like below.</p>
  <p><strong>WeatherFragment</strong></p>
  <pre><code>class WeatherFragment : Fragment() {
  
      @Inject
      lateinit var viewModelFactory: ViewModelFactory
  
      override fun onAttach(context: Context) {
          injector.fragmentComponent().create().injectWeatherFragment(this)
          super.onAttach(context)
      }
  
      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  
          val mainActivityViewModel =
              ViewModelProvider(this,viewModelFactory)[WeatherViewModel::class.java]
          mainActivityViewModel.printMessage()
      }
  
  }
  </code></pre>
  <p>This part is working fine. The Log message inside <code>printMessage()</code> getting printed. I saw in the dagger issue discussion that using <a href="https://github.com/square/AssistedInject" rel="nofollow noreferrer">AssistedInject</a> is the best approach to handle this kind of scenario. I changed my <code>ViewModle</code> by adding a simple int value as a parameter.</p>
  <p><strong>Edited WeatherViewModel</strong></p>
  <pre><code>class WeatherViewModel @AssistedInject constructor(val repository: WeatherRepository,
                                                     @Assisted val id: Int): ViewModel() {
  
      @AssistedInject.Factory
      interface Factory{ fun create(id: Int) : WeatherViewModel }
  
      fun printMessage(){
          Log.d(&quot;WeatherViewModel&quot;,&quot;ViewModel binding is working&quot;)
          repository.printMessage()
      }
  }
  </code></pre>
  <p><strong>Edited ApplicationComponent</strong></p>
  <pre><code>@Singleton
  @Component(modules = [AppModule::class, SubComponentsModule::class, ViewModelFactoryModule::class, AssistedInjectModule::class])
  interface ApplicationComponent {
  
      @Component.Factory
      interface Factory {
          fun create(@BindsInstance applicationContext: Context): ApplicationComponent
      }
  
      fun activityComponent(): ActivitySubComponent.Factory
      fun fragmentComponent(): FragmentSubComponent.Factory
  
  }
  
  @AssistedModule
  @Module(includes = [AssistedInject_AssistedInjectModule::class])
  interface AssistedInjectModule
  </code></pre>
  <p>From this point onwards I don't understand how to inject <code>ViewModel</code> into fragment with repository plus dynamic &quot;id&quot; value. If I inject <code>WeatherViewModel.Factory</code> into the fragment by calling the create method (<code>val mainActivityViewModel = factory.create(5)</code>) it won't fulfill the repository dependency in <code>ViewModel</code>. How to combine these two solutions to have pre-defined repository dependency with dynamic value? OR is there any other better way of approaching this?</p>