Hilt ViewModel 没有零参数构造函数
Hilt ViewModel has no zero argument constructor
Cannot create an instance of class com.comp.app.winners.WinnersViewModel
Caused by: java.lang.InstantiationException: java.lang.Class<com.comp.app.winners.WinnersViewModel> has no zero argument constructor
尝试使用 hilt 解析片段上的视图模型时出错
// Proj
ext.hilt_version = '2.32-alpha'
ext.lifecycle_version = "2.2.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
// App
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
kapt "com.google.dagger:hilt-compiler:$hilt_version"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha03'
implementation "androidx.fragment:fragment-ktx:1.1.0"
@HiltAndroidApp
class MyApplication : Application()
@Module
@InstallIn(SingletonComponent::class)
class ApplicationModule {
@Provides
fun provideService(): MyService = MyServiceImpl()
}
@AndroidEntryPoint
class HomeActivity : AppCompatActivity() {
// Fragment is added here
private fun openFragment(fragment: Fragment) =
supportFragmentManager.beginTransaction().apply {
replace(R.id.container, fragment)
addToBackStack(null)
commit()
}
}
@AndroidEntryPoint
class WinnersFragment: Fragment() {
private val viewModel: WinnersViewModel by viewModels()
}
@HiltViewModel
class WinnersViewModel @Inject constructor(
private val service: MyService
) : ViewModel()
片段还有什么要处理的吗?
我需要以某种方式提供 viewModel 吗?
注意:这是 crash/runtime-error,不是编译错误
您需要升级到 Fragment 1.2.0 或更高版本。
根据 Lifecycle 2.2.0 release notes,Hilt 在后台使用的新 ViewModelProvider
API 仅在使用 Fragment 1.2.0 或更高版本时适用。使用旧版本的片段时,那些 API 未连接到片段,因此当您使用 by viewModels()
.
时,不会使用启用了 Hilt 的 ViewModel 工厂
您应该升级到 Fragment 1.2.5(Fragment 1.2.X 集的最新版本)或 Fragment 1.3.0,两者都包含必要的 API 挂钩以获取刀柄工作。
我的问题与我的 ViewModel 无关,而是与应用它的片段有关。
我的 ViewModel 看起来像
@HiltViewModel
class MyViewModel @Inject constructor(repository: MyRepository): ViewModel() {
这是正确的,但我仍然遇到异常Caused by: java.lang.InstantiationException: java.lang.Class<com.myapp.MyViewModel> has no zero argument constructor
但是,我错过了片段上的 AndroidEntryPoint
注释。将其添加回去解决了我的问题,即
@AndroidEntryPoint
class MyFragment: Fragment() {
private val viewModel: MyViewModel by viewModels()
...
}
如果在使用 compose 时出现此错误,可能是因为您正在使用 NavHost
和 NavHostController
。根据official documentation:
If your @HiltViewModel annotated ViewModel is scoped to the navigation graph, use the hiltViewModel composable function that works with fragments or activities that are annotated with @AndroidEntryPoint.
hiltViewModel
是专用 Hilt + Compose Navigation 依赖项的一部分:
dependencies {
// 1.0.0-beta01 at time of this writing.
// official docs linked above appear to auto update the version
implementation("androidx.hilt:hilt-navigation-compose:[version]")
}
以下是同一文档中提供的 hiltViewModel
调用的上下文示例:
// import androidx.hilt.navigation.compose.hiltViewModel
@Composable
fun MyApp() {
NavHost(navController, startDestination = startRoute) {
composable("example") { backStackEntry ->
// Creates a ViewModel from the current BackStackEntry
// Available in the androidx.hilt:hilt-navigation-compose artifact
val exampleViewModel = hiltViewModel<ExampleViewModel>()
ExampleScreen(exampleViewModel)
}
/* ... */
}
}
Cannot create an instance of class com.comp.app.winners.WinnersViewModel
Caused by: java.lang.InstantiationException: java.lang.Class<com.comp.app.winners.WinnersViewModel> has no zero argument constructor
尝试使用 hilt 解析片段上的视图模型时出错
// Proj
ext.hilt_version = '2.32-alpha'
ext.lifecycle_version = "2.2.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
// App
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
kapt "com.google.dagger:hilt-compiler:$hilt_version"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha03'
implementation "androidx.fragment:fragment-ktx:1.1.0"
@HiltAndroidApp
class MyApplication : Application()
@Module
@InstallIn(SingletonComponent::class)
class ApplicationModule {
@Provides
fun provideService(): MyService = MyServiceImpl()
}
@AndroidEntryPoint
class HomeActivity : AppCompatActivity() {
// Fragment is added here
private fun openFragment(fragment: Fragment) =
supportFragmentManager.beginTransaction().apply {
replace(R.id.container, fragment)
addToBackStack(null)
commit()
}
}
@AndroidEntryPoint
class WinnersFragment: Fragment() {
private val viewModel: WinnersViewModel by viewModels()
}
@HiltViewModel
class WinnersViewModel @Inject constructor(
private val service: MyService
) : ViewModel()
片段还有什么要处理的吗? 我需要以某种方式提供 viewModel 吗?
注意:这是 crash/runtime-error,不是编译错误
您需要升级到 Fragment 1.2.0 或更高版本。
根据 Lifecycle 2.2.0 release notes,Hilt 在后台使用的新 ViewModelProvider
API 仅在使用 Fragment 1.2.0 或更高版本时适用。使用旧版本的片段时,那些 API 未连接到片段,因此当您使用 by viewModels()
.
您应该升级到 Fragment 1.2.5(Fragment 1.2.X 集的最新版本)或 Fragment 1.3.0,两者都包含必要的 API 挂钩以获取刀柄工作。
我的问题与我的 ViewModel 无关,而是与应用它的片段有关。
我的 ViewModel 看起来像
@HiltViewModel
class MyViewModel @Inject constructor(repository: MyRepository): ViewModel() {
这是正确的,但我仍然遇到异常Caused by: java.lang.InstantiationException: java.lang.Class<com.myapp.MyViewModel> has no zero argument constructor
但是,我错过了片段上的 AndroidEntryPoint
注释。将其添加回去解决了我的问题,即
@AndroidEntryPoint
class MyFragment: Fragment() {
private val viewModel: MyViewModel by viewModels()
...
}
如果在使用 compose 时出现此错误,可能是因为您正在使用 NavHost
和 NavHostController
。根据official documentation:
If your @HiltViewModel annotated ViewModel is scoped to the navigation graph, use the hiltViewModel composable function that works with fragments or activities that are annotated with @AndroidEntryPoint.
hiltViewModel
是专用 Hilt + Compose Navigation 依赖项的一部分:
dependencies {
// 1.0.0-beta01 at time of this writing.
// official docs linked above appear to auto update the version
implementation("androidx.hilt:hilt-navigation-compose:[version]")
}
以下是同一文档中提供的 hiltViewModel
调用的上下文示例:
// import androidx.hilt.navigation.compose.hiltViewModel
@Composable
fun MyApp() {
NavHost(navController, startDestination = startRoute) {
composable("example") { backStackEntry ->
// Creates a ViewModel from the current BackStackEntry
// Available in the androidx.hilt:hilt-navigation-compose artifact
val exampleViewModel = hiltViewModel<ExampleViewModel>()
ExampleScreen(exampleViewModel)
}
/* ... */
}
}