SavedStateViewModelFactory with Hilt

250 Views Asked by At

How to use SavedStateViewModelFactory with hilt initialization ?

I read about savedstate and all the developers initialize it without hilt And when I'm trying to initialize it with hilt like this :

 private val imagePickerViewModel: ImagePickerViewModel by viewModels {
        SavedStateViewModelFactory(activity?.applicationContext as Application, this)
    }

It gives me that error :

09-23 17:47:45.872 27177-27177/com.payback.imagepicker E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.payback.imagepicker, PID: 27177
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.payback.imagepicker/com.payback.imagepicker.manager.base.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.payback.imagepicker.presentation.ui.image_picker.ImagePickerViewModel
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
        at android.app.ActivityThread.-wrap11(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
     Caused by: java.lang.RuntimeException: Cannot create an instance of class com.payback.imagepicker.presentation.ui.image_picker.ImagePickerViewModel
        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:221)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:278)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:112)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:54)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelProvider.kt:41)
        at com.payback.imagepicker.presentation.ui.image_picker.ImagePickerFragment.getImagePickerViewModel(ImagePickerFragment.kt:30)
        at com.payback.imagepicker.presentation.ui.image_picker.ImagePickerFragment.observeImageList(ImagePickerFragment.kt:73)
        at com.payback.imagepicker.presentation.ui.image_picker.ImagePickerFragment.onCreateView(ImagePickerFragment.kt:45)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2963)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:518)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
        at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
        at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3065)
        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2988)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
        at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
        at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
        at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
        at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:3072)
        at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:251)
        at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:502)
        at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1237)
        at android.app.Activity.performStart(Activity.java:6253)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
        at android.app.ActivityThread.-wrap11(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5417) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
     Caused by: java.lang.InstantiationException: java.lang.Class<com.payback.imagepicker.presentation.ui.image_picker.ImagePickerViewModel> has no zero argument constructor
        at java.lang.Class.newInstance(Native Method)
        at androidx.lifecycle.ViewModelProvider$NewInstanceFact

How can I initialize SavedStateViewModelFactory to use it with viewmodel and to use it when the app is rotated ?

1

There are 1 best solutions below

0
On

If you want to use savedStateHandler with your viewModel Hilt provides an easier way now to do this, please make sure that dagger is setup with your app and then you can just do the following in fragment and viewModel:

@HiltViewModel
class SomeViewModel @Inject constructor(
    val savedStateHandle: SavedStateHandle
) : ViewModel() { } 

And then in your fragment you can use Fragment.viewModels delegate

@AndroidEntryPoint
class ActiveOrdersFragment : Fragment() {
    private val viewModel: ActiveOrdersViewModel by viewModels()
}

At the moment Im using the following dependencies for hilt :

    implementation "com.google.dagger:hilt-android:2.41"
    kapt "com.google.dagger:hilt-android-compiler:2.40.5"
    kapt 'androidx.hilt:hilt-compiler:1.0.0'
    implementation 'androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03'
    implementation 'androidx.hilt:hilt-work:1.0.0'
    // for delegate 
    implementation "androidx.fragment:fragment-ktx:1.5.0"