Reputation: 23
My code:
@Component(
modules = [
AndroidSupportInjectionModule::class,
ActivityBuildersModule::class,
ViewModelFactoryModule::class
]
)
interface AppComponent : AndroidInjector<BaseApplication> {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): AppComponent
}
}
@Module
abstract class ActivityBuildersModule {
@ContributesAndroidInjector(
modules = [MainActivityViewModelModule::class]
)
abstract fun contributeMainActivity(): MainActivity
}
@Module
abstract class MainActivityViewModelModule {
@Binds
@IntoMap
@ViewModelKey(MainActivityViewModel::class)
public abstract fun bindMainActivityViewModel(mainActivityViewModel: MainActivityViewModel): ViewModel
}
class MainActivityViewModel @Inject constructor(application: Application) : AndroidViewModel(application) {
// empty for now
}
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
public @interface ViewModelKey {
Class<? extends ViewModel> value();
}
class MainActivity : AppCompatActivity() { <-- I made mistake here. I must Extend DaggerAppCompatActivity instead of AppCompatActivity.
// doesn't work for now
@Inject
lateinit var viewModelProviderFactory: ViewModelProviderFactory
lateinit var mainActivityViewModel: MainActivityViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mainActivityViewModel = ViewModelProvider(this, viewModelProviderFactory).get(MainActivityViewModel::class.java)
setMainFragment()
}
private fun setMainFragment() {
// my code
}
}
It gives me an error: lateinit property viewModelProviderFactory has not been initialized.
The same code works fine in another project in Java.
Upvotes: 1
Views: 249
Reputation: 1183
I can be wrong here, but I think you need a ViewModelFactory in your viewModelModule, like this:
@Module
abstract class MainActivityViewModelModule {
@Binds
@IntoMap
@ViewModelKey(MainActivityViewModel::class)
public abstract fun bindMainActivityViewModel(mainActivityViewModel: MainActivityViewModel): ViewModel
@Binds
abstract fun provideViewModelFactory(
factory: ViewModelFactory
): ViewModelProvider.Factory
}
class ViewModelFactory @Inject constructor(
private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): 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)
}
}
}
Upvotes: 0