Android LiveData – Wie kann dasselbe ViewModel für verschiedene Aktivitäten wiederverwendet werden?

Lesezeit: 5 Minuten

Benutzeravatar von user1209216
Benutzer1209216

Beispiel 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;
    }

}

Hauptaktivität:

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);

Ich möchte anrufen mModel.getCurrentName().setValue(anotherName); in der zweiten Aktivität und lassen Sie MainActivity Änderungen empfangen. Ist das möglich?

  • Die “richtige” Antwort lautet: “Wenn Sie Daten zwischen ihnen austauschen möchten, sollten es keine unterschiedlichen Aktivitäten sein, und Sie sollten stattdessen Fragmente austauschen”.

    – EpicPandaForce

    19. März 2018 um 14:34 Uhr

  • @EpicPandaForce vielleicht, aber so funktioniert weder die AndroidStudio Master/Detail-Vorlage noch die Android Architecture Blueprints

    – Markieren

    10. Juli 2018 um 6:09 Uhr

  • @Mark, das ist dann ein Fehler der Android Architecture Blueprints und der Vorlage.

    – EpicPandaForce

    25. Januar 2019 um 22:00 Uhr


  • Bitte lesen Sie dies unter http://stackoverflow.com/questions/56521969/…

    – Levon Petrosjan

    10. Juni 2019 um 16:12 Uhr

Benutzeravatar von Saeed Masoumi
Said Masoumi

Wenn du anrufst ViewModelProviders.of(this)erstellen/behalten Sie tatsächlich eine ViewModelStore was gebunden ist thisalso haben unterschiedliche Aktivitäten unterschiedliche ViewModelStore und jede ViewModelStore erstellt eine andere Instanz von a ViewModel mit einer bestimmten Fabrik, also können Sie nicht die gleiche Instanz von a haben ViewModel an verschiedenen ViewModelStores.

Sie können dies jedoch erreichen, indem Sie eine einzelne Instanz einer benutzerdefinierten ViewModel-Factory übergeben, die als Singleton-Factory fungiert, sodass immer dieselbe Instanz von Ihnen übergeben wird ViewModel zwischen verschiedenen Aktivitäten.

Zum Beispiel:

public class SingletonNameViewModelFactory extends ViewModelProvider.NewInstanceFactory {


    NameViewModel t;

    public SingletonNameViewModelFactory() {
      //  t = provideNameViewModelSomeHowUsingDependencyInjection
    }

    @Override
    public NameViewModel create(Class<NameViewModel> modelClass) {
        return t;
    }
}

Was Sie also brauchen, ist zu machen SingletonNameViewModelFactory Singleton (z. B. mit Dagger) und verwenden Sie es wie folgt:

mModel = ViewModelProviders.of(this,myFactory).get(NameViewModel.class);

Notiz:

Bewahren ViewModels zwischen verschiedenen Bereichen ist ein Anti-Pattern. Es wird dringend empfohlen, Ihre Datenschichtobjekte beizubehalten (z. B. Ihre DataSource oder Ihr Repository zu einem Singleton zu machen) und Ihre Daten zwischen verschiedenen Bereichen (Aktivitäten) aufzubewahren.

Lesen Dies Artikel für Details.

  • Wenn Sie bereits Daten in einer Singleton-Datenschicht zwischenspeichern, was ist dann der Sinn von ViewModel?

    – EpicPandaForce

    19. März 2018 um 14:36 ​​Uhr


  • @EpicPandaForce, ich meine, egal wie sich Ihre Datenschicht verhält, ViewModel müssen Sie irgendwie über Ihre Datenänderungen informieren. Das Zwischenspeichern Ihrer Datenschicht ist also eine Möglichkeit, Ihre Daten in verschiedenen Bereichen zu verwalten.

    – Said Masoumi

    19. März 2018 um 14:43 Uhr

  • Nun, ja, ich denke, Sie haben Recht, ich sollte das nicht versuchen. Aber was ist mit Fragment, ist es eine gute Praxis, untergeordnete Fragmente dazu zu bringen, dasselbe Ansichtsmodell zu beachten? Zum Beispiel ViewModelProviders.of(getActivity()).get(NameViewModel.class) Inneres Fragment.

    – Benutzer1209216

    20. März 2018 um 6:48 Uhr

  • @ user1209216 Ja, warum nicht diesen Artikel für Details lesen developer.android.com/topic/libraries/architecture/…

    – Said Masoumi

    20. März 2018 um 9:19 Uhr

  • Wie erreichen wir dies, wenn wir DaggerViewModelFactory verwenden?

    – Morteza Rastgoo

    17. August 2019 um 11:36 Uhr

Benutzeravatar von TotoliciCristian
TotoliciCristian

Wenn Sie das Ansichtsmodell mithilfe der ViewModelProviders abrufen, die Sie als Lebenszykluseigentümer der MainActivity übergeben, ergibt dies das Ansichtsmodell für diese Aktivität. In der zweiten Aktivität erhalten Sie eine andere Instanz dieses ViewModel, diesmal für Ihre zweite Aktivität. Das zweite Modell wird eine zweite Live-Daten haben.

Was Sie tun können, ist, die Daten in einer anderen Ebene zu verwalten, z. B. einem Repository, das ein Singleton sein kann, und auf diese Weise können Sie dasselbe Ansichtsmodell verwenden.

Geben Sie hier die Bildbeschreibung ein

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

  • Dies sollte eine akzeptierte Antwort sein … ohne das Android-Architekturmuster zu verletzen

    – sum20156

    29. Dezember 2020 um 13:40 Uhr

  • Auch diese Vorgehensweise wird empfohlen hier in diesem offiziellen Tutorial: LiveData in repositories: To avoid leaking ViewModels and callback hell, repositories can be observed

    – Alierdogan7

    17. Juni 2021 um 9:43 Uhr


Erstellen Sie einfach die Instanz Ihrer ViewModelin diesem Fall NameViewModel

Ihre ViewModel Factory mag sein

class ViewModelFactory : ViewModelProvider.NewInstanceFactory() {

    override fun <T : ViewModel?> create(modelClass: Class<T>) =
        with(modelClass){
            when {
                isAssignableFrom(NameViewModel::class.java) -> NameViewModel.getInstance()
                else -> throw IllegalArgumentException("Unknown viewModel class $modelClass")
            }
        } as T


    companion object {
        private var instance : ViewModelFactory? = null
        fun getInstance() =
            instance ?: synchronized(ViewModelFactory::class.java){
                instance ?: ViewModelFactory().also { instance = it }
            }
    }
}

Und Ihr ViewModel

class NameViewModel : ViewModel() {

    //your liveData objects and many more...

    companion object {
        private var instance : NameViewModel? = null
        fun getInstance() =
            instance ?: synchronized(NameViewModel::class.java){
                instance ?: NameViewModel().also { instance = it }
            }
    }
}

Jetzt können Sie verwenden ViewModelProviders um dieselbe Instanz Ihres ViewModel zur Verwendung in jeder Aktivität zu erhalten

ViewModelProviders.of(this, ViewModelFactory.getInstance()).get(NameViewModel::class.java)

ODER

Erstellen Sie eine Erweiterungsfunktion für einen einfacheren Zugriff

fun <T : ViewModel> AppCompatActivity.getViewModel(viewModelClass: Class<T>) =
    ViewModelProviders.of(this, ViewModelFactory.getInstance()).get(viewModelClass)

  • Ich habe diese Lösung ausprobiert, aber es funktioniert nicht. Versuch, eine TextView in einem Fragment aus einer zweiten Aktivität zu aktualisieren.

    – Samuel

    23. Januar 2020 um 20:49 Uhr

  • Können Sie sich meine Einreichung ansehen: stackoverflow.com/questions/59887014/…

    – Samuel

    23. Januar 2020 um 21:06 Uhr

Benutzeravatar von Darrell Burk
Darrell Burk

ViewModel-Bereich/-Lebenszyklus ist an eine Aktivität gebunden, einfach weil der ViewModelStoreOwner, den Sie an den ViewModelProvider-Konstruktor übergeben, zufällig die Aktivität ist.

Da Sie den ViewModelStoreOwner bereitstellen können, können Sie genauso einfach einen bereitstellen, der einen längeren Lebenszyklus hat, z. B. die Anwendung.

Du kannst

  1. Stellen Sie Ihre eigene Unterklasse von Application bereit und implementieren Sie ViewModelStoreOwner (und haben Sie einen ViewModelStore).
  2. Übergeben Sie in ViewModelProvider-Konstruktoraufrufen activity.application anstelle von activity.

Dadurch interagiert der ViewModelProvider mit dem ViewModelStore auf Anwendungsebene, sodass Sie ViewModel-Instanzen mit Anwendungsbereich erstellen können.

1431680cookie-checkAndroid LiveData – Wie kann dasselbe ViewModel für verschiedene Aktivitäten wiederverwendet werden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy