Exemple ViewModel:
public class NameViewModel extends ViewModel {
// Create a LiveData with a String
private MutableLiveData<String> mCurrentName;
public MutableLiveData<String> getCurrentName() {
if (mCurrentName == null) {
mCurrentName = new MutableLiveData<>();
}
return mCurrentName;
}
}
Activité principale:
mModel = ViewModelProviders.of(this).get(NameViewModel.class);
// Create the observer which updates the UI.
final Observer<String> nameObserver = textView::setText;
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
mModel.getCurrentName().observe(this, nameObserver);
Je veux appeler mModel.getCurrentName().setValue(anotherName);
dans la deuxième activité et faire en sorte que MainActivity reçoive les modifications. Est-ce possible?
Lorsque vous appelez ViewModelProviders.of(this)
, vous créez/conservez en fait un ViewModelStore
qui est lié à this
, donc différentes activités ont différentes ViewModelStore
et chaque ViewModelStore
crée une instance différente d'un ViewModel
à l'aide d'une fabrique donnée, vous ne pouvez donc pas avoir la même instance d'un ViewModel
dans différents ViewModelStore
s.
Mais vous pouvez y parvenir en passant une seule instance d'une fabrique ViewModel personnalisée qui agit comme une fabrique singleton, donc elle passera toujours la même instance de votre ViewModel
entre différentes activités.
Par exemple:
public class SingletonNameViewModelFactory extends ViewModelProvider.NewInstanceFactory {
NameViewModel t;
public SingletonNameViewModelFactory() {
// t = provideNameViewModelSomeHowUsingDependencyInjection
}
@Override
public NameViewModel create(Class<NameViewModel> modelClass) {
return t;
}
}
Donc, ce dont vous avez besoin est de créer SingletonNameViewModelFactory
singleton (par exemple en utilisant Dagger) et de l'utiliser comme ceci:
mModel = ViewModelProviders.of(this,myFactory).get(NameViewModel.class);
Remarque:
La conservation de ViewModel
s entre différentes étendues est un anti-modèle. Il est fortement recommandé de conserver vos objets de couche de données (par exemple, rendre votre DataSource ou Repository singleton) et de conserver vos données entre différentes étendues (activités).
Lisez l'article this pour plus de détails.
Lorsque vous obtenez le modèle de vue à l'aide des ViewModelProviders que vous transmettez en tant que propriétaire du cycle de vie à MainActivity, cela donnera le modèle de vue pour cette activité. Dans la deuxième activité, vous obtiendrez une instance différente de ce ViewModel, cette fois pour votre deuxième activité. Le deuxième modèle aura une deuxième donnée en direct.
Ce que vous pouvez faire est de conserver les données dans une couche différente, comme un référentiel, qui peut être un singleton et de cette façon, vous pouvez utiliser le même modèle de vue.
public class NameViewModel extends ViewModel {
// Create a LiveData with a String
private MutableLiveData<String> mCurrentName;
public MutableLiveData<String> getCurrentName() {
if (mCurrentName == null) {
mCurrentName = DataRepository.getInstance().getCurrentName();
}
return mCurrentName;
}
}
//SingleTon
public class DataRepository
private MutableLiveData<String> mCurrentName;
public MutableLiveData<String> getCurrentName() {
if (mCurrentName == null) {
mCurrentName = new MutableLiveData<>();
}
return mCurrentName;
}
//Singleton code
...
}