[英]Cannot create an instance of class ViewModel
I am trying to write a sample app using Android architecture components and but even after trying for days I could not get it to work.我正在尝试使用 Android 架构组件编写一个示例应用程序,但即使尝试了几天我也无法让它工作。 It gives me the above exception.
它给了我上述例外。
Lifecycle owner:-生命周期所有者:-
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());
}
}
});
}
}
ViewModel:-视图模型:-
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;
}
}
如果您使用的是Hilt
,请确保您的活动/片段具有@AndroidEntryPoint
注释
将您的构造函数public
。
Make sure your ViewModel
has constructor with only one parameter ie Application
. 确保
ViewModel
构造函数只有一个参数,即Application
。
example: 例:
public YourViewModel(Application application) {
super(application);
...
I had this problem following google's roomdb CodeLab .我在 google 的roomdb CodeLab之后遇到了这个问题。 Solution was changing the following.
解决方案是更改以下内容。
Add the following Build dependencies to Gradle file (as of 2/22/2020)将以下构建依赖项添加到 Gradle 文件(截至 2/22/2020)
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'
Imports within the fragment片段内的导入
import androidx.lifecycle.ViewModelProvider;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
Creating the viewModel.创建视图模型。 Add one of the following methods.
添加以下方法之一。
Note : I'v seen this done many ways.注意:我见过很多方法。 I believe the correct way is using
getDefaultViewModelProviderFactory()
.我相信正确的方法是使用
getDefaultViewModelProviderFactory()
。 But I have been using requireActivity()
.但我一直在使用
requireActivity()
。
new ViewModelProvider(requireActivity(),getDefaultViewModelProviderFactory()).get(YourViewModel.class);
| |
new ViewModelProvider(requireActivity()).get(YourViewModel.class);
ViewModelProvider Docs ViewModelProvider 文档
Deprecated
已弃用
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-rc01'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.2.0-rc01'
If you are using Kotlin
make sure to replace any annotationProcessor
in build.gradle
with kapt
. 如果您使用的
Kotlin
确保更换任何annotationProcessor
中build.gradle
与kapt
。
Like: 喜欢:
annotationProcessor "android.arch.persistence.room:compiler:$rootProject.roomVersion"
Will become 会变成
kapt "android.arch.persistence.room:compiler:$rootProject.roomVersion"
and add 并添加
apply plugin: 'kotlin-kapt'
on top of the buidl.gradle
file. 在
buidl.gradle
文件顶部apply plugin: 'kotlin-kapt'
。
DggerHilt也可能是原因,如果您正在使用它,请确保您的activity/fragment
上有@AndroidEntryPoint
注释。
It was not completely obvious to me, but when getting this error I resolved it by creating a public constructor. 这对我来说并不完全明显,但是在遇到此错误时,我通过创建一个公共构造函数解决了该错误。 My constructor was derived from the Android Developer examples and contained the Repository as a parameter.
我的构造函数来自Android Developer示例,并且包含Repository作为参数。 Creating an additional constructor that was empty with no params and having it public solved the issue.
创建一个没有参数且为空的附加构造函数并将其公开解决了该问题。
ie, in your case 即,在您的情况下
public PostViewModel() {}
Make sure to use the hiltNavGraphViewModel
instead of viewModel
.确保使用
hiltNavGraphViewModel
而不是viewModel
。
This is provided by androidx.hilt:hilt-navigation-compose
dependency.这是由
androidx.hilt:hilt-navigation-compose
依赖项提供的。
公开类和构造器可以解决我的问题。
There are few reason to throw the exception . 没有什么理由抛出异常。 I have mention some of them..
我提到了其中一些。
Make sure your view model class constructor is public 确保您的视图模型类构造函数是公共的
Make sure you have added the dependency in your gridle file for lifecycle also if you use room and other libries you have added .. 如果您使用房间和其他已添加的库,请确保已在生命周期的网格文件中添加了依赖项。
If you used viewmodel inside your activity check that your activity extends "DaggerAppCompatActivity" or not 如果您在活动中使用了viewmodel,请检查您的活动是否扩展了“ DaggerAppCompatActivity”
For instance 例如
public class UserComments extends AppCompatActivity
change this to 更改为
public class UserComments extends DaggerAppCompatActivity
If you are using Hilt then don't forget to add these four dependencies.如果您正在使用 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"
Note:- If any of these dependencies are missing you will get Cannot create an instance of class ViewModel
error注意:- 如果缺少这些依赖项中的任何一个,您将收到
Cannot create an instance of class ViewModel
错误
Please add below code.请添加以下代码。 It worked for me
它对我有用
val binding = FragmentLayoutBinding.inflate(inflater, container, false)
val viewModel = ViewModelProvider(
requireActivity(),
defaultViewModelProviderFactory
).get(MainViewModel::class.java)
在 viewModel 之上添加 @HiltViewModel 。
I got this after migrating to AndroidX. 迁移到AndroidX后,我得到了这个。
There's a bug in androidx.lifecycle:lifecycle-viewmodel:2.0.0-beta01
where Proguard removes the constructor. androidx.lifecycle:lifecycle-viewmodel:2.0.0-beta01
中存在一个错误,其中Proguard会删除该构造函数。
https://issuetracker.google.com/issues/112230489 https://issuetracker.google.com/issues/112230489
Fix by upgrading to 2.0.0, and remember to update your proguard rules if needed. 通过升级到2.0.0进行修复,并记住在需要时更新您的proguard规则。
My error message looked like this: 我的错误消息如下所示:
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)
Extend AndroidViewModel from your ViewModel class. 从ViewModel类扩展AndroidViewModel 。
public class YourViewModel extends AndroidViewModel {
public YourViewModel(Application application) {
super(application);
//Todo: ...
}
}
如果您的PostViewModel类是内部类,请确保其公共和静态
In my case, it was gradle a dependencies problem.就我而言,它是 gradle 依赖关系问题。
If you are using Livedata,,如果您使用的是 Livedata,
build.gradle(Module.app) build.gradle(Module.app)
not不是
implementation 'android.arch.lifecycle:extensions:1.1.1'
kapt 'android.arch.lifecycle:common-java8:1.1.1'
use these使用这些
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
kapt 'androidx.lifecycle:lifecycle-common-java8:2.2.0'
If you're using Hilt Dependency Injection, You probably have missed @ViewModelInject .如果您正在使用 Hilt 依赖注入,您可能已经错过了@ViewModelInject 。 Because, Hilt provide its own injection for viewmodel.
因为,Hilt 为视图模型提供了自己的注入。
In my case, I used and @Inject due to this caught into the error.就我而言,我使用了 @Inject ,因为这陷入了错误。
如果您在 Kotlin Dagger Hilt 中遇到此问题,即使在 @HiltViewModel 并使用 @Inject 之后,请确保您已更新所有刀柄依赖项。
I'm using this example android-arcuitecture-component BasicSample to make a new project, facing a similar error log, found I did'n change de applicatio name 我正在使用此示例android-arcuitecture-component BasicSample制作一个新项目,面临类似的错误日志,发现我没有更改应用名称
AndroidManifest.xml
AndroidManifest.xml
and that was my error, to fix put the aplicacion name to de BasicApp, this class is implement in the example. 那是我的错误,要修复将aplicacion名称放到de BasicApp中,该类在示例中实现。
...
<application
android:name=".BasicApp"
android:allowBackup="false"
就我而言,我需要使用ListItemViewModelFactory将参数传递给我的视图模型。
创建一个没有参数且为空的附加构造函数并将其公开解决了该问题。
In my case the reason was that I was trying to get shared instance of the ViewModel in my fragment to soon - before the activity was created. 以我为例,原因是我试图在创建活动之前不久将片段中ViewModel的共享实例获取。 That happens when application is restoring its state after being killed.
当应用程序被杀死后恢复其状态时,会发生这种情况。
Preconditions : 前提条件 :
Code in activity: 活动中的代码:
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]
}
Code in fragment: 片段代码:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//fragment receives the instance of MapViewModel
viewModel = ViewModelProviders.of(activity!!)[MapViewModel::class.java]
...
}
When I open the app for the first time, everything works fine: activity creates instance of ViewModel; 当我第一次打开应用程序时,一切正常:活动创建ViewModel实例; I open Fragment, which get the instance of ViewModel.
我打开Fragment,它获取ViewModel的实例。 But when when application is trying to restore its state after being killed, first it calls the body of onCreate of the Fragment and then the body of onCreate of the Activity.
但是,当应用程序被杀死后试图恢复其状态时,它首先调用Fragment的onCreate主体,然后调用Activity的onCreate主体。 At that point fragment can't get the ViewModel as Activity had not created it yet.
此时,片段无法获取ViewModel,因为Activity尚未创建它。
Solution 1 : Move the code when fragment get the ViewModel from onCreate to onViewCreated. 解决方案1 :当片段将ViewModel从onCreate移到onViewCreated时,移动代码。 Which is fine as I observe all liveDatas in onViewCreated as well.
就像我在onViewCreated中观察所有liveData一样,这很好。
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 })
...
}
Solution 2 : Create the instance of ViewModel in Activity.onCreate before super.onCreate is called. 解决方案2 :在调用super.onCreate之前,在Activity.onCreate中创建ViewModel的实例。 In this case you can get the ViewModel in your fragment's onCreate .
在这种情况下,您可以在片段的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 ")
}
我的问题是 IDE 向我的 ViewModel 类添加了一个“抽象”修饰符。
公开ViewModal 类和构造
If constructor of your viewmodel is public and accepts only application then make sure you can create your own model without ViewModelProvider
.如果您的视图模型的构造函数是公共的并且只接受应用程序,那么请确保您可以在没有
ViewModelProvider
情况下创建自己的模型。 Error message might be much more clear:错误信息可能更清楚:
val model = YouViewModel(app)
I'm a proficient Android developer and I have used ViewModel 100s of times with no issue.我是一名熟练的 Android 开发人员,我已经使用 ViewModel 100 次了,没有任何问题。 Today I came across this issue.
今天我遇到了这个问题。 Spent hours and scrolled through various SO posts.
花了几个小时滚动浏览各种 SO 帖子。 Didn't get solved.
没有得到解决。
Then I saw that the package name in which I have the ViewModel contains new
.然后我看到我拥有 ViewModel 的包名称包含
new
。 Like this:像这样:
com.myapp.myfeature.new.feature
I changed new
to neww
for testing like this: com.myapp.myfeature.neww.feature
我换了
new
对neww
测试是这样的: com.myapp.myfeature.neww.feature
and it worked!它奏效了! I hope someone find it useful.
我希望有人觉得它有用。
If you are using version 2.33-beta and upper remove these dependencies;如果您使用的是 2.33-beta 和 upper 版本,请删除这些依赖项;
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0-beta01"
Keep only these two dependency只保留这两个依赖
implementation "com.google.dagger:hilt-android:2.33-beta"
kapt "com.google.dagger:hilt-android-compiler:2.33-beta"
In case you are using Jepack Compose with a ViewModel
in your component .如果您在组件中使用带有
ViewModel
Jepack Compose。 The @Preview
annotation may cause this error. @Preview
注释可能会导致此错误。 That was the problem in my case.这就是我的问题。
Hope it helps someone!希望它可以帮助某人!
I fixed the same problem by doing this.我通过这样做解决了同样的问题。
Note:- I am using Dagger hilt, Room database, MVVM, Data binding注意:-我正在使用 Dagger hilt、Room 数据库、MVVM、数据绑定
Added the 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)
}
}
}
To到
@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)
}
}
}
I had a different scenario when creating a view model instance:创建视图模型实例时,我遇到了不同的情况:
Solution In a scenario where your viewmodel requires a parameter to be passed you have to create a ViewModelFactory to define your instances解决方案在您的视图模型需要传递参数的情况下,您必须创建一个 ViewModelFactory 来定义您的实例
Solution In Practice实践中的解决方案
- ViewModel Sample class SharedViewModel(private val repository: UserRepository) : ViewModel() { init { viewModelScope.launch { repository.refreshDataInDb() } } } - Creating ViewModel Factory class ViewModelFactory( private val repository: UserRepository ) : ViewModelProvider.NewInstanceFactory(){ override fun <T : ViewModel> create(modelClass: Class<T>): T { return SharedViewModel( repository as UserRepository) as T } } - Creating ViewModel Instannce in a Fragment private lateinit var factory: ViewModelFactory private lateinit var searchViewModel: SharedViewModel private lateinit var repository: UserRepository repository = UserRepository() factory = ViewModelFactory(repository) searchViewModel = ViewModelProvider(requireActivity(), factory)[SharedViewModel::class.java]<\/code><\/pre>"
Well this will fix the issue for sure好吧,这肯定会解决问题
First of all make sure you have this dependency首先确保你有这个依赖
//Room DB
implementation "androidx.room:room-runtime:2.2.5"
annotationProcessor 'android.arch.persistence.room:compiler:1.1.1'
Then remove viewmodel constructor, then create init function as your constructor然后删除 viewmodel 构造函数,然后创建 init function 作为您的构造函数
public void init(Application application){
instance = new FirebaseDatabaseInstance();
databaseRepository = new DatabaseRepository(application);
allChatMembers = databaseRepository.getAllChatMembers();
}
Then this will solve...那么这将解决...
Not for OP's case, but adding it here for newcomers.不是针对 OP 的情况,而是在此处为新手添加它。
If you inherit from AndroidViewModel and there is some heavy work in the main Thread (like accessing the database) it'll wrongly throw this error.如果你从AndroidViewModel继承并且在主线程中有一些繁重的工作(比如访问数据库),它会错误地抛出这个错误。
After I switched to inherit from ViewModel , it showed the correct error and I could move the heavy work to Dispatchers.IO
.在我切换到从ViewModel继承后,它显示了正确的错误,我可以将繁重的工作移至
Dispatchers.IO
。 After moving UI blocking stuff to Dispatchers.IO
, I re-tested using AndroidViewModel and everything works fine again.将 UI 阻塞内容移至
Dispatchers.IO
后,我使用AndroidViewModel重新测试,一切正常。
Conclusion: "UI blocking work on the main thread when inheriting from AndroidViewModel can throw this error".结论:“从AndroidViewModel继承时,主线程上的 UI 阻塞工作可能会引发此错误”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.