【问题标题】:Cannot create an instance of class ViewModel无法创建类 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;
    }
}

【问题讨论】:

    标签: android mvvm android-architecture-components


    【解决方案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】:

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

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

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

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

    4. 如果您在视图模型中创建任何其他依赖类的对象 类构造函数。其他类可以抛出错误来创建 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】:
                1. 大多数情况下,解决方案是将 Class 和 Constructor Public 作为其他答案
                2. 也可能是运行时错误,如果列出了多个原因,请查看 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 的共享实例 - 在创建活动之前。当应用程序在被杀死后恢复其状态时会发生什么。

                前提条件:

                1. 我的 ViewModel 有一个公共构造函数。
                2. 我的 ViewModel 有多个参数。但这绝对没问题,因为我使用 ViewModelFactory 来构造 ViewModel。
                3. 我的片段和活动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 ComponentInfo{my.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 注解可能会导致此错误。这就是我的问题。

                                    希望对某人有所帮助!

                                    【讨论】:

                                      猜你喜欢
                                      • 2021-11-28
                                      • 1970-01-01
                                      • 2018-11-02
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多