5

I am trying to add Room database with Android ViewModel. I followed this link for the same https://codelabs.developers.google.com/codelabs/android-room-with-a-view/#13

I am getting an exception :

Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.dailyfaithapp.ViewModels.FavouritesViewModel

I checked some questions and answers on SO, but none working for me.

Here is my view model

public class FavouritesViewModel extends ViewModel {

        public FavouriteRepository mRepository;

        public LiveData<List<Favourites>> mAllFavourites;

    public FavouritesViewModel (Application application) {
            mRepository = new FavouriteRepository(application);
            mAllFavourites = mRepository.getmAllFavourites();
        }

        public LiveData<List<Favourites>> getmAllFavourites() { return mAllFavourites; }

        public void insert(Favourites favourites) { mRepository.insertFavourite(favourites); }

}

I also tried to Call View model using view model factory but did not work here it is

public class FavouritesViewModelFactory implements ViewModelProvider.Factory {
    private Application mApplication;
    private String mParam;


    public FavouritesViewModelFactory(Application application) {
        mApplication = application;
    }


    @Override
    public <T extends ViewModel> T create(Class<T> modelClass) {
        return (T) new FavouritesViewModel(mApplication);
    }
}

I am creating an instance like this after trying many options following SO:

    favouritesViewModel = new ViewModelProvider(this,
            new ViewModelProvider.NewInstanceFactory()).get(FavouritesViewModel.class);

Here is my gradle

  implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
    implementation 'com.jaeger.statusbarutil:library:1.4.0'
    implementation 'androidx.viewpager2:viewpager2:1.1.0-alpha01'
    implementation "com.github.skydoves:balloon:1.1.5"
    implementation 'com.afollestad.material-dialogs:core:3.3.0'
    annotationProcessor 'org.projectlombok:lombok:1.18.12'

    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"

    // Test helpers
    testImplementation "androidx.room:room-testing:$room_version"

Please help. Thank you.

Taslim Oseni
  • 6,086
  • 10
  • 44
  • 69
Sid
  • 2,792
  • 9
  • 55
  • 111
  • I see FavouritesViewModel is expecting application instance while you are passing your activity / fragment instance. Try passing application context and see ? – Tasneem Apr 27 '20 at 15:25
  • If you want your ViewModel to have access to the `Application`, why don't you just use [`AndroidViewModel`](https://developer.android.com/reference/androidx/lifecycle/AndroidViewModel)? – Michael Apr 27 '20 at 15:31
  • I am new to MVVM i just followed some tutorial, if this is not working which is the better way to do this? @Michael – Sid Apr 28 '20 at 06:35

3 Answers3

1

Your ViewModel needs a ViewModel factory class to instantiate. I code in Kotlin and I also faced the same problem the below link provides the answer but in kotlin. https://codelabs.developers.google.com/codelabs/kotlin-android-training-view-model/#7

For Additional Info check this:

https://github.com/android/architecture-components-samples/blob/master/BasicRxJavaSample/app/src/main/java/com/example/android/observability/ui/ViewModelFactory.java

EDIT This is my view model factory class of one of my projects

class AccountspageViewModelFactory
 (
    private val dataSource: accountDao,

    private val application: Application
) : ViewModelProvider.Factory {
    @Suppress("unchecked_cast")
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(AccountspageViewModel::class.java)) {
            return AccountspageViewModel(dataSource,application) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

and this is how I instantiated it in fragment

 val application = requireNotNull(this.activity).application
        val dataSource = accountsdatabase.getInstance(application)?.accountdao

        val viewModelFactory = dataSource?.let { AccountspageViewModelFactory(it,application) }
        val viewModel =
            ViewModelProviders.of(this, viewModelFactory).get(AccountspageViewModel::class.java)\

Change it according to your project but this is in kotlin

Ashu
  • 97
  • 2
  • 11
1

You can try this. `

import androidx.lifecycle.AndroidViewModel;

public class FavouritesViewModel extends AndroidViewModel {
        public FavouriteRepository mRepository;
        public LiveData<List<Favourites>> mAllFavourites;

        public FavouritesViewModel(Application application) {
            super(application)
            mRepository = new FavouriteRepository(application);
            mAllFavourites = mRepository.getmAllFavourites();
        }

        public LiveData<List<Favourites>> getmAllFavourites() { 
            return mAllFavourites; 
        }

        public void insert(Favourites favourites) {   
            mRepository.insertFavourite(favourites);
        }
}

`

Now when you want to create an instance of this you can do something like this.

FavouritesViewModel viewModel = new ViewModelProvider
        .AndroidViewModelFactory(this.getApplication())
        .create(FavouritesViewModel.class);
  • The important bit here is inheriting from `AndroidViewModel` - this allows access to your Application class inside the ViewModel. In this case `AndroidViewModelFactory` is sufficient. See https://developer.android.com/reference/androidx/lifecycle/AndroidViewModel. – user3347392 Sep 20 '22 at 14:22
0

You should create the instance of ViewModel like this

favouritesViewModel = new ViewModelProvider(this,
        new FavouritesViewModelFactory()).get(FavouritesViewModel.class);

Or also you could use

favouritesViewModel = ViewModelProviders.of(this,
        new FavouritesViewModelFactory()).get(FavouritesViewModel.class)

hope this helps you.

Amit Gupta
  • 633
  • 1
  • 8
  • 19
  • I tried both, 1st one is givong same error, for second i am getting java.lang.StackOverflowError: stack size 8192KB this error. I provided this.getAppliction to FAvouritesModelViewFactory. Also increased stack size to org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M" still gettingg an error – Sid Apr 28 '20 at 06:31