title: Dagger 2: multi-module project, inject dependency but get "lateinit property repository has not been initialize" error at runtime
body: <p>Dagger version is 2.25.2.</p>
  
  <p>I have two Android project modules: <code>core</code> module &amp; <code>app</code> module.  </p>
  
  <p>In <code>core</code> module, I defined for dagger <code>CoreComponent</code> , </p>
  
  <p>In <code>app</code> module I have <code>AppComponent</code> for dagger.</p>
  
  <p><code>CoreComponet</code> in core project module:</p>
  
  <pre><code>@Component(modules = [MyModule::class])
  @CoreScope
  interface CoreComponent {
     fun getMyRepository(): MyRepository
  }
  </code></pre>
  
  <p>In core project module, I have a repository class, it doesn't belong to any dagger module but I use <code>@Inject</code> annotation next to its constructor:</p>
  
  <pre><code>class MyRepository @Inject constructor() {
     ...
  }
  </code></pre>
  
  <p>My app component:</p>
  
  <pre><code>@Component(modules = [AppModule::class], dependencies = [CoreComponent::class])
  @featureScope
  interface AppComponent {
      fun inject(activity: MainActivity)
  }
  </code></pre>
  
  <p>In <code>MainActivity</code>:</p>
  
  <pre><code>class MainActivity: AppCompatActivity() {
  
      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContentView(R.layout.activity_main)
  
          val coreComponent = DaggerCoreComponent.builder().build()
  
          DaggerAppComponent
                    .builder()
                    .coreComponent(coreComponent)
                    .build()
                    .inject(this)
       }
  
  }
  </code></pre>
  
  <p>My project is MVVM architecture, In general:</p>
  
  <ul>
  <li><p><code>MainActivity</code> hosts <code>MyFragment</code></p></li>
  <li><p><code>MyFragment</code> has a reference to <code>MyViewModel</code> </p></li>
  <li><p><code>MyViewModel</code> has dependency <code>MyRepository</code> (as mentioned above <code>MyRepository</code> is in <code>core</code> module)</p></li>
  </ul>
  
  <p>Here is <code>MyViewModel</code> :</p>
  
  <pre><code>class MyViewModel : ViewModel() {
      // Runtime error: lateinit property repository has not been initialize
      @Inject
      lateinit var repository: MyRepository
  
      val data = repository.getData()
  
  }
  </code></pre>
  
  <p><code>MyViewModel</code> is initialized in MyFragment:</p>
  
  <pre><code>class MyFragment : Fragment() {
     lateinit var viewModel: MyViewModel
  
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
          super.onViewCreated(view, savedInstanceState)
  
          viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
          ...
      }
  }
  </code></pre>
  
  <p>When I run my app, it crashes with runtime error:</p>
  
  <pre><code>kotlin.UninitializedPropertyAccessException: lateinit property repository has not been initialize
  </code></pre>
  
  <p>The error tells me dagger dependency injection does't work with my setup. So, what do I miss? How to get rid of this error?</p>
  
  <p><strong>==== update =====</strong></p>
  
  <p>I tried :</p>
  
  <pre><code>class MyViewModel @Inject constructor(private val repository: MyRepository): ViewModel() {
          val data = repository.getData()
      }
  </code></pre>
  
  <p>Now when I run the app, I get new error:</p>
  
  <pre><code>Caused by: java.lang.InstantiationException: class foo.bar.MyViewModel has no zero argument constructor
  </code></pre>
  
  <p><strong>====== update 2 =====</strong></p>
  
  <p>Now, I created <code>MyViewModelFactory</code>:</p>
  
  <pre><code>class MyViewModelFactory @Inject constructor(private val creators: Map&lt;Class&lt;out ViewModel&gt;,
                                              @JvmSuppressWildcards Provider&lt;ViewModel&gt;&gt;): ViewModelProvider.Factory {
  
      override fun &lt;T : ViewModel&gt; create(modelClass: Class&lt;T&gt;): T {
          val creator = creators[modelClass] ?: creators.entries.firstOrNull {
              modelClass.isAssignableFrom(it.key)
          }?.value ?: throw IllegalArgumentException("unknown model class $modelClass")
          try {
              @Suppress("UNCHECKED_CAST")
              return creator.get() as T
          } catch (e: Exception) {
              throw RuntimeException(e)
          }
  
      }
  }
  </code></pre>
  
  <p>I updated MyFragment to be :</p>
  
  <pre><code>class MyFragment : Fragment() {
     lateinit var viewModel: MyViewModel
     @Inject
  lateinit var viewModelFactory: ViewModelProvider.Factory
  
     override fun onAttach(context: Context) {
      // inject app component in MyFragment
      super.onAttach(context)
      (context.applicationContext as MyApplication).appComponent.inject(this)
  }
  
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
          super.onViewCreated(view, savedInstanceState)
          // I pass `viewModelFactory` instance here, new error here at runtime, complaining viewModelFactory has not been initialized
          viewModel = ViewModelProviders.of(this, viewModelFactory).get(MyViewModel::class.java)
          ...
      }
  }
  </code></pre>
  
  <p>Now I run my app, I get new error:</p>
  
  <pre><code>kotlin.UninitializedPropertyAccessException: lateinit property viewModelFactory has not been initialized
  </code></pre>
  
  <p>What's still missing?</p>