103

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

32 回答 32

143

制作你的构造函数public

于 2017-07-09T15:33:59.273 回答
121

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

于 2020-08-18T14:55:55.010 回答
24

如果您正在使用,请Kotlin确保将任何annotationProcessorinbuild.gradle替换为kapt.

喜欢:

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

会变成

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

并添加

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

使用 Kotlin 进行注释处理

于 2018-07-29T05:12:43.067 回答
19

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

例子:

public YourViewModel(Application application) {
    super(application);
    ...
于 2018-07-21T18:52:19.257 回答
13

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

已编辑

将以下构建依赖项添加到 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'

片段内的导入

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 文档

已弃用

implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-rc01'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.2.0-rc01'
于 2020-01-06T02:00:40.860 回答
12

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

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

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

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

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

于 2018-11-07T06:22:55.650 回答
11

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

于 2020-12-18T19:09:44.050 回答
6

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

即,在你的情况下

public PostViewModel() {}

于 2018-01-03T01:49:47.407 回答
5

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

于 2018-05-21T07:19:05.030 回答
4

If you used viewmodel inside your activity check that your activity extends "DaggerAppCompatActivity" or not

For instance

public class UserComments extends AppCompatActivity 

change this to

public class UserComments extends DaggerAppCompatActivity
于 2019-05-17T18:11:36.497 回答
4

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

确保使用hiltNavGraphViewModel代替viewModel

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

文档中的更多详细信息。

于 2021-04-19T20:05:55.940 回答
4

从您的 ViewModel 类扩展AndroidViewModel 。

public class YourViewModel extends AndroidViewModel {

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

        //Todo: ...
    }

}
于 2019-04-19T20:54:28.117 回答
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错误

于 2020-06-25T20:54:30.850 回答
3

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

前提条件

  1. 我的 ViewModel 有一个公共构造函数。
  2. 我的 ViewModel 有多个参数。但这绝对没问题,因为我使用 ViewModelFactory 来构造 ViewModel。
  3. 我的 Fragment 和 Activity共享相同的 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主体。此时,片段无法获取 ViewModel,因为 Activity 尚未创建它。

解决方案 1:将片段从 onCreate 获取 ViewModel 时移动代码到 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()**

于 2019-11-21T07:47:49.157 回答
3
  1. 大多数情况下,解决方案是将 Class 和 Constructor Public 作为其他答案
  2. 也可能是运行时错误,如果列出了多个原因,请检查 Logcat 错误日志。
于 2018-12-23T23:55:27.560 回答
3

在您的 viewModel 上添加 @HiltViewModel 。

于 2021-08-31T06:59:10.487 回答
2

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

于 2021-05-05T07:22:05.130 回答
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)
于 2019-03-15T11:14:20.387 回答
2

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

于 2019-07-01T09:58:19.860 回答
2

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

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

val viewModel = ViewModelProvider(
            requireActivity(),
            defaultViewModelProviderFactory
            ).get(MainViewModel::class.java)
于 2020-08-13T15:35:41.683 回答
1

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

在我的情况下,我使用了 @Inject 并因此陷入了错误。

于 2021-03-10T18:04:20.440 回答
1

在我的情况下,我需要使用 ListItemViewModelFactory 将参数传递给我的视图模型。

于 2019-07-24T21:07:43.267 回答
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'
于 2020-02-16T16:50:33.037 回答
1

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

注意:- 我正在使用 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)
        }
    }
}
于 2021-10-28T16:34:47.400 回答
0

将 ViewModal 类和构造公开

于 2020-04-27T10:57:12.120 回答
0

对于与 Jetpack Compose 一起使用的 ViewModel


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

希望它可以帮助某人!

于 2021-09-19T12:46:47.850 回答
0

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

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

com.myapp.myfeature.new.feature

我改为new进行neww这样的测试: com.myapp.myfeature.neww.feature

它奏效了!我希望有人觉得它有用。

于 2020-12-03T12:02:33.353 回答
0

我的问题是 IDE 在我的 ViewModel 类中添加了一个“ abstract ”修饰符。

于 2020-02-03T18:52:03.657 回答
0

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

val model = YouViewModel(app)
于 2020-05-25T11:57:55.587 回答
0

如果您使用的是 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"
于 2021-04-09T22:52:43.423 回答
0

创建视图模型实例时,我遇到了不同的情况:

  1. 我正在请求片段中的实例。
  2. 我的 ViewModel 需要在构造函数上传递一个参数。
  3. 我没有使用依赖注入。

解决方案在您的视图模型需要传递参数的情况下,您必须创建一个 ViewModelFactory 来定义您的实例

实践中的解决方案

- 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]
于 2022-02-04T08:02:41.950 回答
-1

我正在使用这个示例android-arcuitecture-component BasicSample创建一个新项目,遇到类似的错误日志,发现我没有更改应用程序名称

AndroidManifest.xml

那是我的错误,要修复将应用程序名称设置为 de BasicApp,该类在示例中实现。

...
<application
    android:name=".BasicApp"
    android:allowBackup="false"
于 2019-05-19T18:25:24.807 回答