web-dev-qa-db-fra.com

Android LiveData - comment réutiliser le même ViewModel sur différentes activités?

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?

14
user1209216

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 ViewModelStores.

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 ViewModels 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.

28
Saeed Masoumi

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.

enter image description here

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
...
}
9
TotoliciCristian