Cannot create an instance of class ViewModel

AndroidMvvmAndroid Architecture-Components

Android Problem Overview


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

Android Solutions


Solution 1 - Android

Make your constructor public.

Solution 2 - Android

if you are using Hilt, ensure your activity/fragment is having @AndroidEntryPoint annotation

Solution 3 - Android

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

Solution 4 - Android

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

example:

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

Solution 5 - Android

DggerHilt can also be the reason, If you are using it make sure your activity/fragment is having @AndroidEntryPoint annotation on it.

Solution 6 - Android

I had this problem following google's roomdb CodeLab. Solution was changing the following.

Edited

Add the following Build dependencies to Gradle file (as of 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(). But I have been using requireActivity().

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

|

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

          

ViewModelProvider Docs

> Deprecated

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

Solution 7 - Android

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 gradle file for lifecycle also if you use room and other libraries 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

Solution 8 - Android

Add @HiltViewModel on top of your viewModel .

Solution 9 - Android

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() {}

Solution 10 - Android

Make the class and constructor public it solved my problem .

Solution 11 - Android

Extend AndroidViewModel from your ViewModel class.

public class YourViewModel extends AndroidViewModel {

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

        //Todo: ...
    }

}

Solution 12 - Android

For people using Jetpack Compose, Navigation and Hilt

Make sure to use the hiltNavGraphViewModel instead of viewModel.

This is provided by androidx.hilt:hilt-navigation-compose dependency.

More details in the docs.

Solution 13 - Android

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

Solution 14 - Android

  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.

Solution 15 - Android

In my case, the reason was that I was trying to get a shared instance of the ViewModel in my fragment too soon - before the activity was created. What happens when the 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. In other words: Activity creates the ViewModel and the 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 an instance of ViewModel; I open Fragment, which gets the instance of ViewModel. But when the 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, the fragment can't get the ViewModel as Activity had not created it yet.

Solution 1: Move the code when the fragment gets the ViewModel from onCreate to onViewCreated. This is fine as I observe all live data 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 ")
}

Solution 3:

If you are injecting repository instance in your ViewModel, Check that you are not using @Inject constructor(...): ViewModel() to inject your repository, but rather **@ViewModelInject constructor(...): ViewModel()**

Solution 16 - Android

If you are using Hilt then don't forget to add these four dependencies.

    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

Solution 17 - Android

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)

Solution 18 - Android

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

Solution 19 - Android

Please add below code. It worked for me

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

val viewModel = ViewModelProvider(
            requireActivity(),
            defaultViewModelProviderFactory
            ).get(MainViewModel::class.java)

Solution 20 - Android

If you face this issue in Kotlin Dagger Hilt even after @HiltViewModel and using @Inject, make sure you have updated all hilt dependencies.

Solution 21 - Android

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

Solution 22 - Android

In my case, it was gradle a dependencies problem.

If you are using Livedata,,

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'

Solution 23 - Android

If you're using Hilt Dependency Injection, You probably have missed @ViewModelInject. Because, Hilt provide its own injection for viewmodel.

In my case, I used and @Inject due to this caught into the error.

Solution 24 - Android

I fixed the same problem by doing this.

Note:- I am using Dagger hilt, Room database, MVVM, Data binding

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

Solution 25 - Android

My problem was that the IDE had added a "abstract" modifier to my ViewModel class.

Solution 26 - Android

Make ViewModal class and constructure public

Solution 27 - Android

If constructor of your viewmodel is public and accepts only application then make sure you can create your own model without ViewModelProvider. Error message might be much more clear:

val model = YouViewModel(app)

Solution 28 - Android

I'm a proficient Android developer and I have used ViewModel 100s of times with no issue. Today I came across this issue. Spent hours and scrolled through various SO posts. Didn't get solved.

Then I saw that the package name in which I have the ViewModel contains new. Like this:

com.myapp.myfeature.new.feature

I changed new to neww for testing like this: com.myapp.myfeature.neww.feature

and it worked! I hope someone find it useful.

Solution 29 - Android

If you are using version 2.33-beta and upper remove these dependencies;

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"

Solution 30 - Android

For ViewModels used with Jetpack Compose

In case you are using Jepack Compose with a ViewModel in your component. The @Preview annotation may cause this error. That was the problem in my case.

Hope it helps someone!

Solution 31 - Android

I had a different scenario when creating a view model instance:

  1. I was requesting for the instance in a fragment.
  2. My ViewModel required a parameter to be passed on the constructor.
  3. I was not using Dependency Injection.

Solution In a scenario where your viewmodel requires a parameter to be passed you have to create a ViewModelFactory to define your instances

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]

Solution 32 - Android

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

 public void init(Application application){
        instance = new FirebaseDatabaseInstance();
        databaseRepository = new DatabaseRepository(application);
        allChatMembers = databaseRepository.getAllChatMembers();
    }

Then this will solve...

Solution 33 - Android

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"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionParag KadamView Question on Stackoverflow
Solution 1 - AndroidCommonsWareView Answer on Stackoverflow
Solution 2 - AndroidYou QiView Answer on Stackoverflow
Solution 3 - AndroidMaxView Answer on Stackoverflow
Solution 4 - AndroidvivekView Answer on Stackoverflow
Solution 5 - AndroidRahulView Answer on Stackoverflow
Solution 6 - Androidthis.mitchView Answer on Stackoverflow
Solution 7 - AndroidHoque MD ZahidulView Answer on Stackoverflow
Solution 8 - AndroidRabindra KhadkaView Answer on Stackoverflow
Solution 9 - AndroidBrandonView Answer on Stackoverflow
Solution 10 - AndroidRaghavPaiView Answer on Stackoverflow
Solution 11 - AndroidZeero0View Answer on Stackoverflow
Solution 12 - AndroidDuncan LukkenaerView Answer on Stackoverflow
Solution 13 - AndroidAfjalur Rahman RanaView Answer on Stackoverflow
Solution 14 - AndroidlomecView Answer on Stackoverflow
Solution 15 - AndroidAndrewView Answer on Stackoverflow
Solution 16 - AndroidiamkdblueView Answer on Stackoverflow
Solution 17 - AndroidLydia RalphView Answer on Stackoverflow
Solution 18 - AndroidLasitha LakmalView Answer on Stackoverflow
Solution 19 - Androidsharma_kunalView Answer on Stackoverflow
Solution 20 - AndroidAbdul MateenView Answer on Stackoverflow
Solution 21 - AndroidLorenView Answer on Stackoverflow
Solution 22 - AndroidJ.DragonView Answer on Stackoverflow
Solution 23 - AndroidSohail PathanView Answer on Stackoverflow
Solution 24 - AndroidQuick learnerView Answer on Stackoverflow
Solution 25 - AndroidDBragionView Answer on Stackoverflow
Solution 26 - AndroidJohn Ruban SinghView Answer on Stackoverflow
Solution 27 - AndroidelevenView Answer on Stackoverflow
Solution 28 - AndroidParas SidhuView Answer on Stackoverflow
Solution 29 - AndroidAhmet B.View Answer on Stackoverflow
Solution 30 - AndroidOmar El HusseinView Answer on Stackoverflow
Solution 31 - AndroidEnos OkelloView Answer on Stackoverflow
Solution 32 - AndroidAdam reubenView Answer on Stackoverflow
Solution 33 - AndroidSebastian DuranView Answer on Stackoverflow