I have a complex screen in my project which I'm breaking in more than one fragment. I'm trying to follow the MVVM architecture for these classes, so which fragment has its own ViewModel
and Contract class.
The issue is that all the ViewModels needs the same object instance (let's call it Book
) to do Room transactions.
Does it have a correct way to share data (or LiveData
) between ViewModels? I know the concept of Shared ViewModel but I don't know if I can apply it to this case. I also thought about using MediatorLiveData
but didn't get a good approach on it too.
I'm thinking about having a class (let's call BookObservableProvider
) with a LiveData<Book>
(or Rx Subject<Book>
) where each ViewModel injects the same instance and load/update always the same value.
Is it a good approach?
The answer is as usual, it depends.
If the reason behind your question is Room access, then it is recmended to have a DataRepository
class that handles all Database access and you just pass that repository singleton to each AndroidViewModel
.
mRepository = ((MainApp) application).getRepository();
In MainApp:
public DataRepository getRepository() {
return DataRepository.getInstance(getDatabase(), mAppExecutors);
}
And the Repository:
public class DataRepository {
private static DataRepository sInstance;
private MediatorLiveData<String> mObservableString;
private DataRepository(final AppDatabase database, final AppExecutors executors) {
mObservableString.addSource(database.myDao().loadString(),
mString -> {
if (database.getDatabaseCreated().getValue() != null) {
mObservableString.postValue(mString);
}
});
}
public static DataRepository getInstance(final AppDatabase database, final AppExecutors executors) {
if (sInstance == null) {
synchronized (DataRepository.class) {
if (sInstance == null) {
sInstance = new DataRepository(database, executors);
}
}
}
return sInstance;
}
// and then your access methods
public LiveData<String> getString() {
return mObservableString;
}
In the repository it is recommended to have a MediatorLivedata if you want to change the reference (source). Otherwise a normal LiveData does the job.
Regarding ViewModels:
In theory each fragment gets it's own Viewmodel. And if you get it by using requireActivity()
as reference, you can get each ViewModel everywhere and have it therefore shared.
As an example:
viewModelA = new ViewModelProvider(requireActivity()).get(ViewModelA.class);
viewModelB = new ViewModelProvider(requireActivity()).get(ViewModelB.class);
This you could call in every Fragment and get the same ViewModel instances. If the DataRepository setup seems overkill to you, make one ViewModel with Room access and load it from every Fragment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With