无法创建类ViewModel的实例


76

我正在尝试使用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());
                }
            }
        });
    }
}

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;
    }
}

Answers:


125

做你的构造函数public


4
这么小的错误,却影响很大。谢谢。
Parag Kadam

4
@ParagKadam:Android Studio不知道生命周期组件需要构造函数是公共的。Android Studio仅遵循通过显式代码引用可以看到的内容。
CommonsWare

20
仍然在片段中获取错误,类和构造函数均已公开。
ahmadalibaloch

4
我的构造函数是公共的,但是我收到此错误:由java.lang.RuntimeException引起:无法在android.arch.lifecycle.ViewModelProvider $ NewInstanceFactory.create(ViewModelProvider)上创建com.randa.android.model.search.SearchActivityViewModel类的实例.java:153),位于android.arch.lifecycle.ViewModelProvider $ AndroidViewModelFactory.create(ViewModelProvider.java:210),位于android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:134),位于android.arch.lifecycle.ViewModelProvider。在com.randa.android中获取(ViewModelProvider.java:102)。
MrVasilev's

2
有趣的是,它可以在调试模式下运行,但是在发布模式下编译应用程序时会崩溃。
mk_

21

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


这不能为问题提供答案。要批评或要求作者澄清,请在其帖子下方发表评论。-评分
安德里Omelchenko

好@AndriiOmelchenko,您是否在viewModel构造函数中尝试了Hilt注入?因为我相信这是大多数开发人员都会犯的一个诚实错误,它将Cannot create an instance of class ViewModel在运行时导致崩溃。
您齐

2
我正在使用Dagger Hilt,这个答案为我节省了很多时间,谢谢!
Canberk Ozcelik

我总是犯同样的错误,发现自己在这里。谢谢。
UmutTekin

19

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

例:

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

1
谢谢,我创建了ViewModel Class的构造函数,得到了两个参数,我删除了一个,并取得了良好的效果。
mortezahosseini

1
是的,它只有一个参数,但仍然崩溃
Jayesh M

2
为什么ViewModel只有一个构造。参数?
IgorGanapolsky

17

如果您使用的Kotlin一定要更换任何annotationProcessorbuild.gradlekapt

喜欢:

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

会变成

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

并添加

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

使用Kotlin进行注释处理


2
它解决了我的问题。对于Java,这可能不是正确的答案,但是对于“无法在Kotlin中创建类ViewModel的实例”是正确的
Eoghan

1
@Eoghan出于完全相同的原因发布了答案,因为花了我相当长的时间才能理解这个问题。但是,即使我使用的是Kotlin,但即使我已经明确提到,ppl都不是温柔的,并且会继续嘲笑大声笑。
最多

它救了我,我讨厌这个Android记录器,我在某些事情上例外,原因实际上是其他事情
Milos

@Milos也许您应该在Android Studio中使用“日志过滤器”。
Ab Morphious

12

我在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;

创建viewModel。添加以下方法之一。

注意:我已经看到了很多方法。我相信正确的方法是使用getDefaultViewModelProviderFactory()。但是我一直在用requireActivity()

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

|

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

          

ViewModelProvider文档

不推荐使用

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

2
最新的android生命周期文档说,不推荐使用lifecycle-extensions依赖developer.android.com/jetpack/androidx/releases/lifecycle#但是,如果我从gradle文件中删除了该依赖关系,我将无法创建类的实例启动应用程序时出现viewmodel错误。我尝试添加列出为当前的所有其他依赖项,甚至是可选的依赖项,但是如果没有lifecycle-extensions依赖项,它将无法正常工作。现在,我必须保留不推荐使用的依赖项。我仍在尝试查找为什么没有这种依赖关系会失败。
霍华德

好的信息@Howard,我根据您的评论更新了我的答案。
this.mitch

感谢这个答案,我有以下roomdb代码实验室,我不得不添加为实现唯一相同的问题“androidx.fragment:片段:1.2.5”
RCK

7

没有什么理由抛出异常。我提到了其中一些。

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

  3. 如果您使用房间和其他已添加的库,请确保已在生命周期的网格文件中添加了依赖项。

  4. 如果创建对象,则在视图模型类构造函数中创建任何其他依赖类。其他类可能引发错误以创建viewModel的实例

1
伟大的第四点!找到您的分步解决方案之后,它确实解决了我。
Vji

6

这对我来说并不完全明显,但是当出现此错误时,我通过创建一个公共构造函数解决了该错误。我的构造函数是从Android Developer示例派生的,并且包含Repository作为参数。创建一个没有参数且为空的附加构造函数并将其公开解决了该问题。

即,在您的情况下

public PostViewModel() {}


如果我们需要将参数传递给ViewModel怎么办?
IgorGanapolsky

您可以为该对象创建一个附加的构造函数,但是要解决此问题,需要使用NoArgsConstructor。
布兰登

官方文件在哪里证明这一点?
IgorGanapolsky


4

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

例如

public class UserComments extends AppCompatActivity 

改成

public class UserComments extends DaggerAppCompatActivity

3
  1. 通常,解决方案是将类和构造函数公开为其他答案
  2. 这也可能是运行时错误,如果列出了多个原因,请检查Logcat错误日志。

1
是的,课堂也很重要public
Kurt Huwig

3

从ViewModel类扩展AndroidViewModel

public class YourViewModel extends AndroidViewModel {

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

        //Todo: ...
    }

}

3

如果您使用的是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。尽管后来被复制了
aNdRO博士20年

这个答案帮助了我。我缺少了 kapt“ androidx.hilt:hilt-compiler:1.0.0-alpha01”。仅此一点就阻止了我的ViewModel(在其构造函数中带有参数,没有ViewModelFactory)的创建。
user1987392

1
你是我的英雄。您节省了我的时间,谢谢
andika_kurniawan

@andika_kurniawan,您可以投票给英雄回答。
iamkdblue

大声笑,确定我会投票
andika_kurniawan

2

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

androidx.lifecycle:lifecycle-viewmodel:2.0.0-beta01Proguard删除构造函数的地方存在一个错误。

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)


1

就我而言,这是一个依赖问题。

如果您使用的是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'

1

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


1

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

前提条件

  1. 我的ViewModel有一个公共构造函数。
  2. 我的ViewModel有多个参数。但这绝对好,因为我使用ViewModelFactory构造ViewModel。
  3. 我的Fragment和Activity共享相同的ViewModel实例。换句话说:活动将创建ViewModel,并且片段稍后将接收相同的实例。

活动中的代码:

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]
    ...
}

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

解决方案1:当片段将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()**


0

就我而言,我需要使用ListItemViewModelFactory将参数传递给我的视图模型。


0

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



0

如果viewmodel的构造函数是公共的,并且仅接受应用程序,那么请确保您可以创建自己的模型而无需ViewModelProvider。错误消息可能更加清晰:

val model = YouViewModel(app)

0

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

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

com.myapp.myfeature.new.feature

我改变了newneww测试是这样的: com.myapp.myfeature.neww.feature

而且有效!我希望有人觉得它有用。


很好,它对您有用,但是它与ViewModels没有任何关系,您不能在包名称中使用关键字。
Parag Kadam

是的Parag,但没有警告,也没有指出错误。唯一随机的事件是发现问题出在软件包名称中
Paras Sidhu

您可能在使用ViewModels以外的其他任何东西时发现了此问题,仅仅是因为在实现ViewModels时发现了此问题并不能使其有效解决上述问题。
Parag Kadam


-1

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

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

val viewModel = ViewModelProvider(
            requireActivity(),
            defaultViewModelProviderFactory
            ).get(MainViewModel::class.java)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.