无法创建类 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