无法创建类 ViewModel 的实例

Posted

技术标签:

【中文标题】无法创建类 ViewModel 的实例【英文标题】:Cannot create an instance of class ViewModel 【发布时间】:2017-12-13 08:41:08 【问题描述】:

我正在尝试使用 android 架构组件编写一个示例应用程序,但即使尝试了几天,我也无法让它工作。它给了我上述异常。

生命周期所有者:-

public class MainActivity extends LifecycleActivity 

    public void onCreate(Bundle savedInstanceState)
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView textView = findViewById(R.id.tv_user);
        PostViewModel viewModel = ViewModelProviders.of(this).get(PostViewModel.class);
        viewModel.loadPosts();
        viewModel.getPost().observe(this, new Observer<Post>() 
            @Override
            public void onChanged(@Nullable Post post) 
                if(post != null) 
                    textView.setText(post.toString());
                
            
        );
    

视图模型:-

public class PostViewModel extends ViewModel 
    private MediatorLiveData<Post> post;
    private PostRepository postRepo;

    PostViewModel() 
        post = new MediatorLiveData<>();
        postRepo = new PostRepository();
    

    public LiveData<Post> loadPosts() 
        post.addSource(postRepo.getPost(),
                post -> this.post.setValue(post)
        );
        return post;
    

    @NonNull
    public LiveData<Post> getPost() 
        return post;
    

【问题讨论】:

【参考方案1】:

让你的构造函数public

【讨论】:

这样一个小错误,但影响如此之大。谢谢。 @ParagKadam:Android Studio 不知道生命周期组件需要构造函数公开。 Android Studio 只按照它可以通过显式代码引用看到的内容。 仍然在片段中收到错误,类和构造函数都已经公开。 我的构造函数是公开的,但我收到了这个错误:由 java.lang.RuntimeException 引起:无法在 android.arch.lifecycle 创建类 com.randa.android.model.search.SearchActivityViewModel 的实例.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:153) 在 android.arch.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:210) 在 android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134) 在com.randa.android 上的 android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:102)。 有趣的是它在调试模式下工作,但在应用程序在发布模式下编译时崩溃。【参考方案2】:

如果您使用Hilt,请确保您的活动/片段具有@AndroidEntryPoint 注释

【讨论】:

这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方留下评论。 - From Review 好吧@AndriiOmelchenko,您是否尝试过在viewModel 构造函数中注入Hilt?因为我相信这是大多数开发人员会犯的一个诚实的错误,这会导致Cannot create an instance of class ViewModel 在运行时崩溃。 我正在使用 Dagger Hilt,这个答案为我节省了很多时间,谢谢! 即使在输入@AndroidEntryPoin 之后,我仍然收到 java.lang.RuntimeException: Cannot create an instance of class ViewModel 最新的@HiltViewModel 在你的viewModel之上【参考方案3】:

如果您使用的是Kotlin,请确保将build.gradle 中的任何annotationProcessor 替换为kapt

喜欢:

annotationProcessor "android.arch.persistence.room:compiler:$rootProject.roomVersion"

会变成

kapt "android.arch.persistence.room:compiler:$rootProject.roomVersion"

并添加

apply plugin: 'kotlin-kapt'buidl.gradle 文件的顶部。

Annotation Processing with Kotlin

【讨论】:

它解决了我的问题。它可能不是 java 的正确答案,但它是正确的“无法在 Kotlin 中创建类 ViewModel 的实例” @Eoghan 我出于完全相同的原因发布了答案,因为我花了很长时间才理解这个问题。但是,即使我已经明确提到您是否使用 kotlin,但 ppl 并不温和并且继续投票。 它救了我,我讨厌这个 android 记录器,我遇到了一些异常,原因实际上是别的东西 @Milos 也许你应该在 Android Studio 中使用“日志过滤器”。【参考方案4】:

确保您的ViewModel 的构造函数只有一个参数,即Application

示例:

public YourViewModel(Application application) 
    super(application);
    ...

【讨论】:

谢谢,我创建 ViewModel 类的构造函数得到两个参数,我删除了一个,结果很好。 是的,它只有一个参数,但它仍然崩溃 为什么ViewModel只能有一个constr.参数?【参考方案5】:

我在 google 的 roomdb CodeLab 之后遇到了这个问题。解决方案正在更改以下内容。

已编辑

将以下构建依赖项添加到 Gradle 文件(截至 2020 年 2 月 22 日)

implementation 'androidx.fragment:fragment:1.2.2'
implementation 'androidx.lifecycle:lifecycle-process:2.2.0'
implementation 'androidx.lifecycle:lifecycle-service:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:2.2.0'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.2.0'

片段内的导入

import androidx.lifecycle.ViewModelProvider;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;

创建视图模型。添加以下方法之一。

注意:我见过很多方法。我相信正确的方法是使用getDefaultViewModelProviderFactory()。但我一直在使用requireActivity()

 new ViewModelProvider(requireActivity(),getDefaultViewModelProviderFactory()).get(YourViewModel.class);

|

 new ViewModelProvider(requireActivity()).get(YourViewModel.class);

          

ViewModelProvider Docs

已弃用

implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-rc01'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.2.0-rc01'

【讨论】:

最新的 android 生命周期文档说生命周期扩展依赖项现在已弃用 developer.android.com/jetpack/androidx/releases/lifecycle# 但是,如果我从 gradle 文件中删除该依赖项,我会收到无法创建类视图模型的实例错误我启动我的应用程序。我尝试添加所有其他列为当前的依赖项,甚至是可选的依赖项,但如果没有生命周期扩展依赖项,它将无法工作。现在,我必须保留已弃用的依赖项。我仍在尝试找出没有这种依赖关系的原因。 好消息@Howard,我根据您的评论更新了我的答案。 感谢您的回答,我在 roomdb CodeLab 之后遇到了同样的问题,我唯一需要添加的是 implementation 'androidx.fragment:fragment:1.2.5'【参考方案6】:

抛出异常的理由很少。我已经提到了其中的一些..

    确保您的视图模型类是公开的

    确保您的视图模型类构造函数是公开的

    确保你已经在你的 gradle 文件中添加了依赖 如果您使用已添加的房间和其他库,生命周期也是如此..

    如果您在视图模型中创建任何其他依赖类的对象 类构造函数。其他类可以抛出错误来创建 viewModel 实例

【讨论】:

非常适合第四点!!!找到您的逐步解决方案后,它真的解决了我。【参考方案7】:

DggerHilt 也可能是原因,如果您正在使用它,请确保您的 activity/fragment 上有 @AndroidEntryPoint 注释。

【讨论】:

【参考方案8】:

这对我来说并不是很明显,但是当我遇到这个错误时,我通过创建一个公共构造函数来解决它。我的构造函数派生自 Android 开发者示例,并包含存储库作为参数。创建一个没有参数的空构造函数并将其公开解决了这个问题。

即,在你的情况下

public PostViewModel()

【讨论】:

如果我们需要给 ViewModel 传参数怎么办?? 你可以为那个创建一个额外的构造函数,但是解决这个问题需要一个 NoArgsConstructor。 官方文档在哪里证明这一点?【参考方案9】:

将类和构造函数公开它解决了我的问题。

【讨论】:

【参考方案10】:

从您的 ViewModel 类中扩展 AndroidViewModel

public class YourViewModel extends AndroidViewModel 

    public YourViewModel(Application application) 
        super(application);

        //Todo: ...
    


【讨论】:

【参考方案11】:

如果您在 Activity 中使用了 viewmodel,请检查您的 Activity 是否扩展了“DaggerAppCompatActivity”

例如

public class UserComments extends AppCompatActivity 

改成

public class UserComments extends DaggerAppCompatActivity

【讨论】:

【参考方案12】:

对于使用 Jetpack Compose、Navigation 和 Hilt 的用户

确保使用hiltNavGraphViewModel 而不是viewModel

这是由androidx.hilt:hilt-navigation-compose 依赖提供的。

更多详情请关注docs。

【讨论】:

【参考方案13】:

在您的 viewModel 上添加 @HiltViewModel 。

【讨论】:

【参考方案14】:
    大多数情况下,解决方案是将 Class 和 Constructor Public 作为其他答案 也可能是运行时错误,如果列出了多个原因,请查看 Logcat 错误日志。

【讨论】:

是的,班级也是public,这一点非常重要。【参考方案15】:

如果你使用 Hilt,那么不要忘记添加这四个依赖项。

    implementation "com.google.dagger:hilt-android:2.28-alpha"
    kapt "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"

注意:- 如果缺少这些依赖项中的任何一个,您将收到 Cannot create an instance of class ViewModel 错误

【讨论】:

我有所有 4 个我仍然收到该错误。我有 2 个视图模型 1 在启动时效果很好 1 在家里给出了这个错误 -__0 。虽然后来被复制了 这个答案对我有帮助。我错过了 kapt "androidx.hilt:hilt-compiler:1.0.0-alpha01"。仅此一项就阻止了我的 ViewModel(在其构造函数中带有参数,没有 ViewModelFactory)被创建。 你是我的英雄。你节省了我的时间,谢谢 @andika_kurniawan 你可以为你的英雄的答案投票。【参考方案16】:

就我而言,原因是我试图在我的片段中过早地获取 ViewModel 的共享实例 - 在创建活动之前。当应用程序在被杀死后恢复其状态时会发生什么。

前提条件

    我的 ViewModel 有一个公共构造函数。 我的 ViewModel 有多个参数。但这绝对没问题,因为我使用 ViewModelFactory 来构造 ViewModel。 我的片段和活动shares the same instance of the ViewModel。换句话说:Activity 创建 ViewModel,Fragment 稍后接收相同的实例。

活动中的代码:

override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)

    //factory is constructed using Dagger
    val factory = App.get().components().appComponent.getMapViewModelFactory() 
    //activity creates the instance of MapViewModel
    viewModel = ViewModelProviders.of(this, factory)[MapViewModel::class.java]

片段中的代码:

override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)

    //fragment receives the instance of MapViewModel
    viewModel = ViewModelProviders.of(activity!!)[MapViewModel::class.java]
    ...

当我第一次打开应用程序时,一切正常:activity 创建了一个 ViewModel 实例;我打开 Fragment,它获取 ViewModel 的实例。但是当应用程序被杀死后试图恢复其状态时,它首先调用Fragment的onCreate主体,然后调用Activity的onCreate主体。此时,fragment 无法获取 ViewModel,因为 Activity 尚未创建它。

解决方案1:将Fragment获取ViewModel时的代码从onCreate移动到onViewCreated。这很好,因为我也观察了 onViewCreated 中的所有实时数据。

override fun onViewCreated(view: View, savedInstanceState: Bundle?) 
    super.onViewCreated(view, savedInstanceState)

    viewModel = activity?.run  ViewModelProviders.of(this)[MapViewModel::class.java]  ?: throw Exception("Invalid Activity")

    viewModel.getSurveyDateLiveData().observe(viewLifecycleOwner, Observer<String>  dateTextView.text = it )
    ...

解决方案 2: 在调用 super.onCreate 之前,在 Activity.onCreate 中创建 ViewModel 的实例。在这种情况下,您可以在片段的 onCreate 中获取 ViewModel。

override fun onCreate(savedInstanceState: Bundle?) 
    
    val factory = App.get().components().appComponent.getMapViewModelFactory()
    viewModel = ViewModelProviders.of(this, factory)[MapViewModel::class.java]
    
    super.onCreate(savedInstanceState)
    Timber.d("cc: onCreate: $this ")

解决方案 3

如果您在 ViewModel 中注入存储库实例,请检查您没有使用 @Inject constructor(...): ViewModel() 来注入存储库,而是使用 **@ViewModelInject constructor(...): ViewModel()**

【讨论】:

【参考方案17】:

我在迁移到 AndroidX 后得到了这个。

androidx.lifecycle:lifecycle-viewmodel:2.0.0-beta01 中有一个错误,Proguard 删除了构造函数。

https://issuetracker.google.com/issues/112230489

通过升级到 2.0.0 来修复,如果需要,记得更新你的 proguard 规则。

我的错误信息如下所示:

java.lang.RuntimeException: Cannot create an instance of class my.custom.viewmodel.CustomViewModel
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:202)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:135)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:103)
......
Caused by: java.lang.NoSuchMethodException: <init> [class android.app.Application]
at java.lang.Class.getConstructor0(Class.java:2204)
at java.lang.Class.getConstructor(Class.java:1683)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:200)
... 34 more


  androidx.test.espresso.PerformException: Error performing 'single click - At Coordinates: 539, 1167 and precision: 16, 16' on view 'with id: my.test:id/button_return_to_main_menu'.
at androidx.test.espresso.PerformException$Builder.build(PerformException.java:82)
at androidx.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:79)
.....
Caused by: java.lang.RuntimeException: Unable to start activity ComponentInfomy.custom.domain.MainActivity: java.lang.RuntimeException: Cannot create an instance of class my.custom.viewmodel.CustomViewModel
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)

【讨论】:

【参考方案18】:

如果您的 PostViewModel 类是内部类,请确保它是公共的和静态的

【讨论】:

【参考方案19】:

请添加以下代码。它对我有用

val binding = FragmentLayoutBinding.inflate(inflater, container, false)

val viewModel = ViewModelProvider(
            requireActivity(),
            defaultViewModelProviderFactory
            ).get(MainViewModel::class.java)

【讨论】:

并在片段/活动上使用 -> @AndroidEntryPoint @umitx 如果你只使用 Hilt 而不是我们必须在 Activity 中执行此操作【参考方案20】:

如果您在使用 @HiltViewModel 并使用 @Inject 之后在 Kotlin Dagger Hilt 中遇到此问题,请确保您已更新所有刀柄依赖项。

【讨论】:

【参考方案21】:

在我的例子中,我需要使用 ListItemViewModelFactory 将参数传递给我的视图模型。

【讨论】:

是的。我们必须创建YourViewModelFactory(private val param: String) : ViewModelProvider.Factory 才能在ViewModel 中包含一个参数。【参考方案22】:

在我的例子中,这是一个 gradle 依赖问题。

如果您使用的是 Livedata,

build.gradle(Module.app)

不是

implementation 'android.arch.lifecycle:extensions:1.1.1'
kapt 'android.arch.lifecycle:common-java8:1.1.1'

使用这些

implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
kapt 'androidx.lifecycle:lifecycle-common-java8:2.2.0'

【讨论】:

【参考方案23】:

如果您使用 Hilt 依赖注入,您可能错过了 @ViewModelInject。因为,Hilt 为 viewmodel 提供了自己的注入。

在我的例子中,我使用了 @Inject 并因此陷入了错误。

【讨论】:

如果您在 Kotlin Dagger Hilt 中遇到此问题,即使在添加注释 HiltViewModel 和 Inject 之后,请确保您已更新所有 hilt 依赖项。【参考方案24】:

我通过这样做解决了同样的问题。

注意:- 我正在使用 Dagger hilt、Room 数据库、MVVM、数据绑定

添加注释。

class AlertViewModel
@Inject
constructor(private val userRepository: AlertRepository) : ViewModel()
    val getList:LiveData<List<Alert>> get() =
        userRepository.getList.flowOn(Dispatchers.Main)
            .asLiveData(context = viewModelScope.coroutineContext)

    fun insert(user:Alert)
        viewModelScope.launch 
            userRepository.insert(user)
        
    

@HiltViewModel // Added this annotation
class AlertViewModel
@Inject
constructor(private val userRepository: AlertRepository) : ViewModel()
    val getList:LiveData<List<Alert>> get() =
        userRepository.getList.flowOn(Dispatchers.Main)
            .asLiveData(context = viewModelScope.coroutineContext)

    fun insert(user:Alert)
        viewModelScope.launch 
            userRepository.insert(user)
        
    

【讨论】:

【参考方案25】:

我的问题是 IDE 向我的 ViewModel 类添加了“abstract”修饰符。

【讨论】:

【参考方案26】:

制作 ViewModal 类并构造 public

【讨论】:

【参考方案27】:

如果您的视图模型的构造函数是公开的并且只接受应用程序,那么请确保您可以在没有ViewModelProvider 的情况下创建自己的模型。错误信息可能更清楚:

val model = YouViewModel(app)

【讨论】:

【参考方案28】:

我是一名熟练的 Android 开发人员,我已经使用 ViewModel 100 多次,没有任何问题。今天我遇到了这个问题。花了几个小时滚动浏览各种 SO 帖子。没解决。

然后我看到我拥有 ViewModel 的包名称包含new。像这样:

com.myapp.myfeature.new.feature

我将 new 更改为 neww 以进行如下测试: com.myapp.myfeature.neww.feature

它成功了!我希望有人觉得它有用。

【讨论】:

很好,它对你有用,但这与 ViewModels 没有任何关系,你不能在包名称中使用关键字。 是的,但没有警告,错误也没有指向它。发现问题出在包名称上只是随机事件 您可能在使用除 ViewModels 之外的任何其他东西时发现了这个问题,仅仅因为您在实施 ViewModels 时发现了这个问题并不能使其成为上述问题的有效答案。【参考方案29】:

如果您使用的是 2.33-beta 及更高版本,请删除这些依赖项;

implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0-beta01"

只保留这两个依赖项

implementation "com.google.dagger:hilt-android:2.33-beta"
kapt "com.google.dagger:hilt-android-compiler:2.33-beta"

【讨论】:

【参考方案30】:

对于与 Jetpack Compose 一起使用的 ViewModel


如果您在 组件 中使用带有 ViewModel 的 Jepack Compose。 @Preview 注解可能会导致此错误。这就是我的问题。

希望对某人有所帮助!

【讨论】:

以上是关于无法创建类 ViewModel 的实例的主要内容,如果未能解决你的问题,请参考以下文章

Dagger/MissingBinding java.util.Map<java.lang.Class<? extends ViewModel>,Provider<ViewMo

无法创建 ViewModel 类的实例

如何修复“无法创建 ViewModel 类的实例”?

Hilt 新组件 | ViewModelComponent

Asp.net Core 如何将 ReflectionIT.Mvc.Paging 与 ViewModel 一起使用?

无法从 ViewModelProvider 创建 ViewModel