Android 中使用 Kotlin 的 Dagger:lateinit 属性 viewModelProviderFactory 尚未初始化
Dagger with Kotlin in Android: lateinit property viewModelProviderFactory has not been initialized
我的代码:
- 应用程序组件:
@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
}
}
- ActivityBuildersModule:
@Module
abstract class ActivityBuildersModule {
@ContributesAndroidInjector(
modules = [MainActivityViewModelModule::class]
)
abstract fun contributeMainActivity(): MainActivity
}
- MainActivityViewModelModule:
@Module
abstract class MainActivityViewModelModule {
@Binds
@IntoMap
@ViewModelKey(MainActivityViewModel::class)
public abstract fun bindMainActivityViewModel(mainActivityViewModel: MainActivityViewModel): ViewModel
}
- MainActivityViewModel:
class MainActivityViewModel @Inject constructor(application: Application) : AndroidViewModel(application) {
// empty for now
}
- ViewModelKey(在Java):
@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
}
}
它给我一个错误:lateinit 属性 viewModelProviderFactory 尚未初始化。
相同的代码在 Java 的另一个项目中工作正常。
扩展 DaggerAppCompatActivity 而不是 AppCompatActivity
我在这里可能是错的,但我认为您的 viewModelModule 中需要一个 ViewModelFactory,如下所示:
@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)
}
}
}
我的代码:
- 应用程序组件:
@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
}
}
- ActivityBuildersModule:
@Module
abstract class ActivityBuildersModule {
@ContributesAndroidInjector(
modules = [MainActivityViewModelModule::class]
)
abstract fun contributeMainActivity(): MainActivity
}
- MainActivityViewModelModule:
@Module
abstract class MainActivityViewModelModule {
@Binds
@IntoMap
@ViewModelKey(MainActivityViewModel::class)
public abstract fun bindMainActivityViewModel(mainActivityViewModel: MainActivityViewModel): ViewModel
}
- MainActivityViewModel:
class MainActivityViewModel @Inject constructor(application: Application) : AndroidViewModel(application) {
// empty for now
}
- ViewModelKey(在Java):
@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
}
}
它给我一个错误:lateinit 属性 viewModelProviderFactory 尚未初始化。
相同的代码在 Java 的另一个项目中工作正常。
扩展 DaggerAppCompatActivity 而不是 AppCompatActivity
我在这里可能是错的,但我认为您的 viewModelModule 中需要一个 ViewModelFactory,如下所示:
@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)
}
}
}