Search code examples
javaandroidandroid-architecture-componentsandroid-viewmodel

How to pass custom parameters to a ViewModel using Factory?


I am aware in order to pass custom parameters to ViewModel, we can use ViewModelProvider.NewInstanceFactory, Like this:

// Factory Class    
class MyFactory extends ViewModelProvider.NewInstanceFactory {

        private final String mId;
        public MyFactory(String id) {
            mId = id;
        }

        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            return (T) new MyViewModel(mId);
        }
    }


// MyViewModel class
class MyViewModel extends ViewModel {

  public MyViewModel(String id) {
     ...
  }
}

// Activity I can Initialise as: 
MyFactory modelFactory = new MyFactory(id);
viewModel = ViewModelProviders.of(this, modelFactory).get(MyViewModel.class);

How can I achieve the same with custom parameters in the AndroidViewModel subclass along with the Application context. Like

// MyAndroidViewModel class
    class MyAndroidViewModel extends AndroidViewModel {

      public MyViewModel(Application context, String id) {
         super(context);
         ...
      }
    }

How to initialise MyAndroidViewModel and how ViewModelProvider.NewInstanceFactory comes into play here?


Solution

  • I had this problem previously and I managed it by doing this. In your activity create your ViewModel factory as below :

    //Inside MyActivity
    ViewModelProvider.Factory factory = new ViewModelProvider.Factory() {
                @NonNull
                @Override
                public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
                    return (T) new MyAndroidViewModel(getApplication(),
                            "My string!");
                }
            };
    

    And then use it to create your ViewModel :

    viewModel = ViewModelProviders.of(this, factory).get(MyAndroidViewModel.class); 
    

    UPDATE:

    As the ViewModelProviders class has been deprecated, the updated answer would be as below. The factory is the same as before, it has just changed to Kotlin.

    var factory = object : ViewModelProvider.Factory {
            override fun <T : ViewModel?> create(modelClass: Class<T>): T {
                return  SimpleAndroidViewModel(activity!!.application,
                    "My string!") as T
            }
        }
    

    However, the line where we were creating the ViewModel instance has changed and now we are using the ViewModelProvider class.

    private val viewModel: SimpleAndroidViewModel by lazy {
            ViewModelProvider(this, factory).get(SimpleAndroidViewModel::class.java)
        }