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.