Android ViewModel is very useful.
However ViewModel has no args constructor by default.
Typical usage of ViewModel looks like:
public class UserModel extends ViewModel {
}
final UserModel viewModel = ViewModelProviders.of(this).get(UserModel.class);
Let's look the definition of ViewModelProviders.of method.
/**
* Creates a {@link ViewModelProvider}, which retains ViewModels while a scope of given Activity
* is alive. More detailed explanation is in {@link ViewModel}.
*
* It uses the given {@link Factory} to instantiate new ViewModels.
*
* @param activity an activity, in whose scope ViewModels should be retained
* @param factory a {@code Factory} to instantiate new ViewModels
* @return a ViewModelProvider instance
*/
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
Have you found it? We can pass a Factory to create the ViewModel.
Implement your own Factory then you can have args constructor for your ViewModel.
Here we set up a ViewModel with 1 argument construcgtor.
Example code:
public QASViewModel(@NonNull FragmentActivity activity) {
this.activity = activity;
}
QASViewModel qasViewModel = ViewModelProviders.of(getActivity(),
new QASViewModelFactory(getActivity())).get(QASViewModel.class);
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import java.lang.reflect.InvocationTargetException;
public class QASViewModelFactory extends ViewModelProvider.NewInstanceFactory {
private final FragmentActivity activity;
/**
* Creates a {@code AndroidViewModelFactory}
*
* @param activity an AssetManager to pass in {@link QASViewModel}
*/
public QASViewModelFactory(@NonNull FragmentActivity activity) {
this.activity = activity;
}
@NonNull
@Override
public T create(@NonNull Class modelClass) {
if (QASViewModel.class.isAssignableFrom(modelClass)) {
try {
return modelClass.getConstructor(FragmentActivity.class).newInstance(activity);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
return super.create(modelClass);
}
}