在 Android 中使用 Hilt 后无法创建视图模型的实例

Cannot create instance of viewmodel after using Hilt in Android

这是我的 AllFilesListViewModel class.

class AllFilesListViewModel @ViewModelInject constructor(
    private val pdfItemRepository: PdfItemRepository):ViewModel() {

}

这里是PdfItemRepositoryclass.

@Singleton
class PdfItemRepository @Inject constructor(private val pdfItemDao: PdfItemDao){

}

对于pdfItemDao。我创建了一个名为 DatabaseModule 的模块。下面是代码 -

@Module
@InstallIn(ApplicationComponent::class)
object DatabaseModule {

    @Provides
    fun provideDatabase(@ApplicationContext context: Context):AppDatabase{
        return AppDatabase.getDataBase(context)
    }

    @Provides
    fun providePdfItemDao(database:AppDatabase):PdfItemDao{
        return database.pdfItemDao()
    }
}

这是我使用 viewModel 的片段 class AllFilesFragment.kt

@AndroidEntryPoint
class AllFilesFragment:Fragment(){

    private lateinit var binding:AllFilesFragmentBinding
    private val viewModel by viewModels<AllFilesListViewModel>()


    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = AllFilesFragmentBinding.inflate(inflater,container,false)
        context?: return binding.root
        initThings()
        subscribeUi()
        return binding.root
    }
}

这里是 logcat 文件。

06-19 19:22:20.203 23753-23753/com.emptysheet.pdfreader_autoscroll E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.emptysheet.pdfreader_autoscroll, PID: 23753
    java.lang.RuntimeException: Cannot create an instance of class com.emptysheet.pdfreader_autoscroll.homeScreen.viewModel.AllFilesListViewModel
        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:221)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:278)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:106)
        at androidx.hilt.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:69)
        at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:69)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:54)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:41)
        at com.emptysheet.pdfreader_autoscroll.homeScreen.AllFilesFragment.getViewModel(AllFilesFragment.kt)
        at com.emptysheet.pdfreader_autoscroll.homeScreen.AllFilesFragment.subscribeUi(AllFilesFragment.kt:72)
        at com.emptysheet.pdfreader_autoscroll.homeScreen.AllFilesFragment.onCreateView(AllFilesFragment.kt:64)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
        at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
        at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:442)
        at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2169)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1992)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1947)
        at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1818)
        at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
        at androidx.viewpager2.adapter.FragmentStateAdapter.placeFragmentInViewHolder(FragmentStateAdapter.java:341)
        at androidx.viewpager2.adapter.FragmentStateAdapter.onViewAttachedToWindow(FragmentStateAdapter.java:276)
        at androidx.viewpager2.adapter.FragmentStateAdapter.onViewAttachedToWindow(FragmentStateAdapter.java:67)
        at androidx.recyclerview.widget.RecyclerView.dispatchChildAttached(RecyclerView.java:7556)
        at androidx.recyclerview.widget.RecyclerView.addView(RecyclerView.java:860)
        at androidx.recyclerview.widget.ChildHelper.addView(ChildHelper.java:107)
        at androidx.recyclerview.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:8601)
        at androidx.recyclerview.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:8559)
        at androidx.recyclerview.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:8547)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1641)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
        at android.view.View.layout(View.java:15689)
        at android.view.ViewGroup.layout(ViewGroup.java:5048)
        at androidx.viewpager2.widget.ViewPager2.onLayout(ViewPager2.java:527)
        at android.view.View.layout(View.java:15689)
        at android.view.ViewGroup.layout(ViewGroup.java:5048)
        at com.google.android.material.appbar.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:148)
        at com.google.android.material.appbar.V

这是由于 AndroidX Lifecycle、AndroidX Core、AndroidX Activity 和 AndroidX Fragment 之间的版本不匹配造成的。

Hilt 仅在 getDefaultViewModelProviderFactory 可以被覆盖时才有效。

仅当该方法确实存在时才成立,如果您的依赖项已过时则不会。也就是说,你的androidx.fragment低于1.2.0,你的androidx.activity低于1.1.0。

使用这个就可以了:

implementation "androidx.appcompat:appcompat:1.1.0"
implementation "androidx.fragment:fragment-ktx:1.2.5"
implementation "androidx.core:core-ktx:1.3.0"
implementation "androidx.activity:activity:1.1.0"

implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0"

但目前,这就是它对我有用的原因:

implementation 'com.google.dagger:dagger:2.28'
kapt 'com.google.dagger:dagger-compiler:2.28'

// hilt
implementation 'com.google.dagger:hilt-android:2.28-alpha'
kapt 'com.google.dagger:hilt-android-compiler:2.28-alpha'
kaptAndroidTest 'com.google.dagger:hilt-android-compiler:2.28-alpha'
kaptTest 'com.google.dagger:hilt-android-compiler:2.28-alpha'
implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha01'
kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01'

一起
 apply plugin: 'dagger.hilt.android.plugin'

    classpath 'com.google.dagger:hilt-android-gradle-plugin:2.28-alpha'
    

我在应用程序的 build.gradle 中使用 kapt 'androidx.hilt:hilt-compiler:1.0.0-alpha01' 后,这个问题就解决了。我已经添加了 kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"。我仍然不明白两个 BTW 之间的区别。如果有人知道。请给我解释一下。

我以前遇到过这个问题,我已经通过将 SavedStateHandle 传递给视图模型的主构造函数来修复它。

class AuthViewModel @ViewModelInject constructor(@Assisted private val savedState: SavedStateHandle) : ViewModel()

我在使用 Hilt 时发生了这种情况,那是因为我忘记在片段 class 的顶部添加 @AndroidEntryPoint 注释。 片段和宿主 activity 都应使用此注释进行注释。

对于那些检查了上述所有解决方案但仍然无法正常工作的人,最后的检查是删除 Build 文件夹和 rebuild 项目,这将强制编译器重新创建匕首dependency graph 引擎盖下。

就我而言,我 annotated 我的 activity 和 @AndroidEntryPoint 仍然面临同样的问题。我删除了我的 build 文件夹和 rebuild 项目,它按预期工作。

@ViewModelInject 在较新的刀柄版本中已弃用

Reference

使用HiltViewModel

@HiltViewModel
class AllFilesListViewModel @Inject constructor(
    val pdfItemRepository: PdfItemRepository)
) : ViewModel() {

}

在 alpha03 中,现在使用新的 @HiltViewModel 和普通的 @Inject,如下所示。

@HiltViewModel
class MyViewModel @Inject constructor(
    private val repository: Repository,
    private val savedStateHandle: SavedStateHandle
) : ViewModel(), LifecycleObserver {

    // Some code
}

我今天也遇到了这个问题,我尝试了所有建议的修复方法,但无法消除错误。我只是 post 我的解决方案,以防将来有人遇到同样的问题。

在我的例子中,我有一个多模块项目,有 'UI module'、'ViewModel module' 和 'Use-cases module'。我这边的错误是我没有导入应用程序 gradle 模块中的所有模块,我只导入了 UI 模块。我在 Android 开发者网站上发现了这条关于刀柄实施的说明:

Note: Because Hilt's code generation needs access to all of the Gradle modules that use Hilt, the Gradle module that compiles your Application class also needs to have all of your Hilt modules and constructor-injected classes in its transitive dependencies.

当我导入生成 DI 图表所需的所有模块时,此崩溃消失了。

当我使用 Jetpack Compose、Hilt 和 Compose Navigation 时,我的做法是获取文档中的所有依赖项,并确保它们的所有版本都是最新的。关键是当你创建 ViewModel 时,你不应该使用 = viewModel(),因为你使用了 Compose Navigation,应该使用 = hiltViewModel()

对我来说,将 = viewModel() 从 Compose 函数移动到 Activity

Jetpack Compose + NavGraph 中的 ViewModel

此答案适用于使用 Jetpack Compose 和导航 (NavGraph) 的人 根据文档中的 Hilt and Navigation,我们必须使用 hiltViewModel 而不是 viewModel 示例:

dependencies {
    implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
}
// 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 viewModel = hiltViewModel<MyViewModel>()
            MyScreen(viewModel)
        }
        /* ... */
    }
}

更多新鲜信息尽在source