Cannot create an instance of class ViewModel

蓝咒 提交于 2019-12-18 12:44:48

问题


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

回答1:


Make your constructor public.




回答2:


Make sure your ViewModel has constructor with only one parameter i.e. Application.

example:

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



回答3:


If you are using Kotlin make sure to replace any annotationProcessor in build.gradle with 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.

Annotation Processing with Kotlin




回答4:


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. Creating an additional constructor that was empty with no params and having it public solved the issue.

i.e., in your case

public PostViewModel() {}




回答5:


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



回答6:


Make the class and constructor public it solved my problem .




回答7:


There are few reason to throw the exception . I have mention some of them..

  1. Make sure your view Model class is public
  2. Make sure your view model class constructor is public

  3. Make sure you have added the dependency in your gridle file for lifecycle also if you use room and other libries you have added ..

  4. if you create object any other dependent class in your view model class constructor . Other class can throw error to create the instance of viewModel



回答8:


  1. Mostly, Solution is making Class and Constructor Public as the other answers
  2. It may also be a runtime error, check the Logcat Error Logs if there are multiple causes listed.



回答9:


I got this after migrating to AndroidX.

There's a bug in androidx.lifecycle:lifecycle-viewmodel:2.0.0-beta01 where Proguard removes the constructor.

https://issuetracker.google.com/issues/112230489

Fix by upgrading to 2.0.0, and remember to update your proguard rules if needed.

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)



回答10:


Extend AndroidViewModel from your ViewModel class.

public class YourViewModel extends AndroidViewModel {

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

        //Todo: ...
    }

}



回答11:


if your PostViewModel class is an inner class, make sure its public and static




回答12:


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

AndroidManifest.xml

and that was my error, to fix put the aplicacion name to de BasicApp, this class is implement in the example.

...
<application
    android:name=".BasicApp"
    android:allowBackup="false"



回答13:


In my case I needed to use a ListItemViewModelFactory to pass in a parameter to my view model.




回答14:


Creating an additional constructor that was empty with no params and having it public solved the issue.




回答15:


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. That happens when application is restoring its state after being killed.

Preconditions:

  1. My ViewModel has a public constructor.
  2. My ViewModel has multiple arguments. But this is absolutely fine as I use ViewModelFactory to construct the ViewModel.
  3. My Fragment and Activity shares the same instance of the ViewModel. Other words: Activity creates the ViewModel and fragment receives the same instance later.

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; I open Fragment, which get the instance of 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. At that point fragment can't get the ViewModel as Activity had not created it yet.

Solution 1: Move the code when fragment get the ViewModel from onCreate to onViewCreated. Which is fine as I observe all liveDatas in onViewCreated as well.

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. In this case you can get the ViewModel in your fragment's onCreate.

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 ")
}


来源:https://stackoverflow.com/questions/44998051/cannot-create-an-instance-of-class-viewmodel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!