ViewModelFactory allows us to produce custom ViewModels that allow for the inclusion of arguments in the Constructor (standard ViewModels do not).
To implement a ViewModelFactory, first create a ViewModelFactory class (this example corresponds to the code in the @Entity, @DAO, Build a Database and LiveData posts):
public class AddContactViewModelFactory extends ViewModelProvider.NewInstanceFactory { private final AppDatabase mDb; private final int mContactId; public AddTaskViewModelFactory(AppDatabase mDb, int mContactId) { // Arguments to be passed in this.mDb = mDb; this.mContactId = mContactId; } // Note: This can be reused with minor modifications @Override public <T extends ViewModel> T create(Class<T> modelClass) { // When ViewModelFactory is created it returns a new ViewModel with the arguments fed in //noinspection unchecked return (T) new AddContactViewModel(mDb, mContactId); } }Then create the class declared in the ViewModelFactory's create() override:
public class AddContactViewModel extends ViewModel { private LiveData<ContactEntry> contactEntry; public AddTaskViewModel(AppDatabase database, int contactId) { // Constructor which takes the arguments contactEntry = database.contactDao().loadContactById(contactId); // Code which retrieves the LiveData object through the @DAO } public LiveData<ContactEntry> getContactEntry() { // Method of delivering the data to the Activity return contactEntry; } }In the Activity:
AddContactViewModelFactory addContactViewModelFactory = new AddContactViewModelFactory(mDb, mContactId); // Feed in arguments to the ViewModelFactory final AddContactViewModel viewModel = ViewModelProviders.of(this, addContactViewModelFactory).get(AddContactViewModel.class); // Create the View Model, including the ViewModelFactory in the arguments viewModel.getContactEntry().observe(this, new Observer<ContactEntry>() { // Observe the LiveData object which is cached in the ViewModel @Override public void onChanged(@Nullable ContactEntry contactEntry) { viewModel.getContactEntry().removeObserver(this); // Not quite sure why we've removed the Observer here populateUI(contactEntry); // Apply changes to UI } });
