ViewModelProviders ist in 1.1.0 veraltet

145

Mit Blick auf die Google Text & Tabellen für ViewModelSie zeigen die folgenden Beispielcode, wie ein bekommen ViewModel:

val model = ViewModelProviders.of(this).get(MyViewModel::class.java)

Bei Verwendung der neuesten Abhängigkeit android.arch.lifecycle:extensions:1.1.1gibt es keine solche Klasse ViewModelProviders.

Gehen zur Dokumentation für ViewModelProviderssah ich einen Kommentar zu sagen:

Diese Klasse wurde in API-Level 1.1.0 nicht mehr unterstützt. Verwenden Sie ViewModelProvider.AndroidViewModelFactory

Das Problem ist, dass beim Versuch, eine zu verwenden ViewModelProvider.AndroidViewModelFactory, keine äquivalente ofMethode zum Abrufen der Instanz von gefunden werden kann ViewModel.

Was ich versucht habe:

ViewModelProvider.AndroidViewModelFactory.getInstance(application).create(PlayerViewHolder::class.java)

Daher der Name der Methode. Bei createjedem Aufruf erhalte ich eine neue Instanz des ViewModel, nach der ich nicht suche.

Irgendwelche Ideen, was ist der Ersatz für veralteten Code oben?

TareK Khoury
quelle
Verwenden Sie ein Singleton-Muster oder wechseln Sie zu AndroidX
Oussema Aroua

Antworten:

31

UPDATE 2020-06-16 : Derzeit ViewModelProviders veraltet und sollte nicht mehr verwendet werden. Diese Frage und Antwort stammte von Ende 2018, als dies nicht der Fall war. Diese Frage und Antwort gilt auch für die ältere Edition von Architecture Components ViewModelProviders, nicht für die AndroidX-Edition.


Bei Verwendung der neuesten Abhängigkeit android.arch.lifecycle:extensions:1.1.1gibt es keine solche Klasse ViewModelProviders.

Ja da ist. Um dies zu demonstrieren:

  • Erstellen Sie ein neues Projekt in Android Studio 3.2.1 (mit Kotlin, minSdkVersion21, Vorlage "Leere Aktivität").

  • Fügen Sie android.arch.lifecycle:extensions:1.1.1zu den Abhängigkeiten des appModuls hinzu

Dies gibt Ihnen ein app/build.gradlewie:

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.commonsware.myandroidarch"
        minSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'android.arch.lifecycle:extensions:1.1.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

Sie werden dann sehen, dass die Bibliothek in "Externe Bibliotheken" mit dieser Klasse angezeigt wird:

Externe Bibliotheken

Und Sie können auf diese Klasse verweisen:

package com.commonsware.myandroidarch

import android.arch.lifecycle.ViewModelProviders
import android.support.v7.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val provider = ViewModelProviders.of(this)
  }
}

In der Dokumentation zu ViewModelProviders wurde ein Kommentar angezeigt, der besagt: Diese Klasse ist in API-Version 1.1.0 veraltet. Verwenden Sie ViewModelProvider.AndroidViewModelFactory

Dieser Kommentar befindet sich unter dem ViewModelProviders.DefaultFactoryKlasseneintrag und bezieht sich auf diese Klasse, nicht auf ViewModelProviders:

Screenshot der Dokumentation

Irgendwelche Ideen, was ist der Ersatz für veralteten Code oben?

Verwenden Sie ViewModelProviders.

CommonsWare
quelle
1
@ TareKKhoury: Das würde es erklären! Es kann eine Herausforderung sein, zu verfolgen, welche Module welche Abhängigkeiten benötigen. Ich bin froh zu hören, dass du es zum Laufen gebracht hast!
CommonsWare
12
Dies ist nicht mehr wahr, ViewModelProviders.of()existiert nicht mehr.
EpicPandaForce
316

Ich verwende die Lifecycle-Extensions- 2.2.0Version:

implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" 

Es sollte Arbeit sein, mit ViewModelProviderKonstruktor.

// With ViewModelFactory   
val viewModel = ViewModelProvider(this, YourViewModelFactory).get(YourViewModel::class.java)


//Without ViewModelFactory
val viewModel = ViewModelProvider(this).get(YourViewModel::class.java)

Update 2020/5/15

Ich finde einen anderen eleganten Weg zu erreichen, Android KTX kann helfen

implementation "androidx.fragment:fragment-ktx:1.2.4"
val viewmodel: MYViewModel by viewModels()
val viewmodel: MYViewModel by viewModels { myFactory } //With factory

Ref: https://developer.android.com/reference/kotlin/androidx/fragment/app/package-summary#viewmodels

25.06.2020: Der Fall des Delegierten wurde korrigiert

Fantasy Fang
quelle
158
Ich habe den ständigen "Abschreibungs" -Zyklus von Google satt.
AFD
3
ViewModelProviders.of () ist veraltet. Sie können ein Fragment oder eine FragmentActivity an den neuen ViewModelProvider-Konstruktor (ViewModelStoreOwner) übergeben, um dieselbe Funktionalität zu erzielen. (aosp / 1009889)
Raghu Krishnan R
31
Java-Äquivalent:YourViewModel viewModel = new ViewModelProvider(this).get(YourViewModel.class);
Ban-Geoengineering
16
Ich mache mir Sorgen, wenn Google eines Tages das TextViewoder ablehnt EditTextund eine neue Komponente einführt.
Pranjal Choladhara
4
androidx lifecycle-viewmodel 2.1.0 hat keinen Konstruktor ohne Factory. einfach (dies) zu verwenden funktioniert nicht. ViewModelProvider (ViewModelStoreOwner, Factory) und ViewModelProvider (ViewModelStore, Factory) sind die einzigen Konstruktoren
DevinM
70

Wie @FantasyFang in seiner Antwort erwähnt hat, verwenden Sie die neueste Version für die, lifecycle:lifecycle-extensionsdie in diesem Moment ist 2.2.0-alpha03. Daher sollten Sie in Ihre build.gradle-Datei die folgende Zeile einfügen:

implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-alpha03' 

Wenn Sie Java verwenden, übergeben Sie diese Argumente zur Lösung dieses Problems direkt an den Konstruktor von ViewModelProvider :

MyViewModel viewModel = new ViewModelProvider(this, myViewModelFactory).get(MyViewModel.class);

Oder wenn Sie keine Fabrik benutzen, benutzen Sie einfach:

MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);

Ohne das Werksobjekt zu übergeben.

Alex Mamo
quelle
1
In build.gradle sollten Sie Folgendes verwenden: Implementierung "androidx.lifecycle: lifecycle-viewmodel: $ lifecycle_version" Wie unter developer.android.com/jetpack/androidx/releases/lifecycle angegeben. Die APIs in Lifecycle-Erweiterungen sind veraltet. Fügen Sie stattdessen Abhängigkeiten für die spezifischen Lifecycle-Artefakte hinzu, die Sie benötigen.
Kenneth Argo
40

Ab 2.2.0. Die Lebenszykluserweiterungen sind veraltet. Siehe Google-Dokumentation .

Dies ist der Ausschnitt aus der Seite:

Die APIs in Lebenszykluserweiterungen sind veraltet. Fügen Sie stattdessen Abhängigkeiten für die spezifischen Lifecycle-Artefakte hinzu, die Sie benötigen.

Die neuen Bibliotheken sind:

// ViewModel and lifecycle support for java
implementation "androidx.lifecycle:lifecycle-viewmodel:${versions.lifecycle}"
implementation "androidx.lifecycle:lifecycle-livedata:${versions.lifecycle}"

// ViewModel and lifecycle support for kotlin
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${versions.lifecycle}"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:${versions.lifecycle}"

Der neue Code für JAVA:

viewModel = new ViewModelProvider(this).get(MyViewModel.class);

Oder für Kotlin:

viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
Kenneth Argo
quelle
Behalten wir die ViewModelProvider-Isntsance bei oder müssen wir sie erneut erstellen. In diesem Fall werden auch alle zugrunde liegenden Instanzen zerstört. Ich habe nicht den Grund, es neu zu erstellen, wenn die Idee darin besteht, den Lebenszyklus des Fragments / der Aktivität zu beobachten
TheRealChx101
31

Veraltet von: ViewModelProviders.of(this, provider).get(VM::class.java)

Zu: ViewModelProvider(this, provider).get(VM::class.java)

Braian Coronel
quelle
4
genau das, wonach ich gesucht habe.
Rahul Bali
20

Anfang 2020 hat Google die ViewModelProviders-Klasse in Version 2.2.0 der AndroidX-Lebenszyklusbibliothek abgelehnt.

Es ist nicht mehr erforderlich, ViewModelProviders zum Erstellen einer Instanz eines ViewModel zu verwenden. Sie können stattdessen Ihre Fragment- oder Aktivitätsinstanz an den ViewModelProvider-Konstruktor übergeben.

Wenn Sie den Code wie folgt verwenden:

val viewModel = ViewModelProviders.of(this).get(CalculatorViewModel::class.java)

Sie erhalten eine Warnung, dass ViewModelProviders veraltet ist.

Nehmen Sie die folgenden Änderungen vor, um die Verwendung veralteter Bibliotheken zu vermeiden:

  1. Verwenden Sie in der Datei build.gradle (Modul: App) Version 2.2.0 der Lebenszykluskomponenten:

    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation "androidx.activity:activity-ktx:1.1.0"

    Wenn Sie stattdessen das ViewModel aus einem Fragment verwenden möchten, verwenden Sie

    implementation "androidx.fragment:fragment-ktx:1.2.2"

    fragment-ktx enthält automatisch activity-ktx, sodass Sie nicht beide in den Abhängigkeiten angeben müssen.

  2. Sie müssen Java 8 im Android-Bereich angeben:

    android {
        compileSdkVersion 28
        defaultConfig {
            applicationId "com.kgandroid.calculator"
            minSdkVersion 17
            targetSdkVersion 28
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner 
        "androidx.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 
               'proguard-rules.pro'
            }
        }
    
        kotlinOptions { jvmTarget = "1.8" }
    }
  3. Ändern Sie in Ihrem Fragment oder Ihrer Aktivität den Import in:

    androidx.activity.viewModels importieren

  4. Der Code zum Erstellen eines ViewModel lautet dann:

    val viewModel: CalculatorViewModel by viewModels()

    anstatt

    val viewModel = ViewModelProviders.of(this).get(CalculatorViewModel::class.java)

    Verwenden Sie das viewModel-Objekt als:

    val viewModel: CalculatorViewModel by viewModels()
    
    viewModel.newNumber.observe(this, Observer<String> { 
        stringResult -> newNumber.setText(stringResult) 
    })

    Dabei ist newNumer ein LiveData-Objekt

    In einem Fragment, das Sie für das ViewModel der Aktivität freigeben möchten, würden Sie es verwenden

    val viewModel: CalculatorViewModel by activityViewModels()

Dies entspricht dem Übergeben der Activity-Instanz in der (veralteten) ViewModelProviders.of()Funktion.

kgandroid
quelle
17

ViewModelProviders.of () ist veraltet. Geben Sie hier die Bildbeschreibung ein

Verwenden Sie ViewModelProvider-Konstruktoren direkt, da sie jetzt die Standardrolle ViewModelProvider.Factory übernehmen.

 mainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);
John
quelle
13

Ja @Tarek, es ist veraltet. Jetzt mit AndroidX verwenden:

val yourViewModel = ViewModelProvider.NewInstanceFactory().create(YourVideoModel::class.java)
Paulo Linhares - Packapps
quelle
5
Diese Antwort ist falsch. Sie sollten ein verwenden, da dies ViewModelProvider(viewModelStoreOwner, factory).get(YourVideoModel::class.java)sonst onCleared()nicht ordnungsgemäß funktioniert und ViewModel bei Konfigurationsänderungen nicht beibehalten wird. Verwenden Sie diese Antwort nicht.
EpicPandaForce
12

Wahrscheinlich können Sie einfach verwenden:

val viewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).get(MyViewModel::class.java)

ohne android.arch.lifecycle:extensions:1.1.1als Abhängigkeit hinzufügen zu müssen .

Xiaoyu
quelle
8

Ich benutze android Xund hatte auch dieses Problem.

Zunächst sollten Sie diese Abhängigkeiten zu Ihrem hinzufügen Gradle:

implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" 

In meinem Fall war die $ lifecycle_version 2.2.0-rc02

Zweitens: Der Import für das ViewModelProvidersollte sein:

import androidx.lifecycle.ViewModelProvider

Dann können Sie Ihr vIewModel wie in den folgenden Beispielen initialisieren:

val viewModel = ViewModelProvider(this, YourFactoryInstace).get(MainViewModel::class.java)

val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
Igor Fridman
quelle
Vielen Dank für Ihre Antwort, aber wenn ich es benutze, dann beobachten Viewmodel und Felder Datenbindung funktioniert nicht mehr
Mosa
Ich glaube androidx.lifecycle:lifecycle-compilerist obsolet von androidx.lifecycle:lifecycle-common-java8.
Bink
8

Was macht die ViewModelProviders.of()Methode eigentlich unter der Haube?

@Deprecated
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull Fragment fragment) {
    return new ViewModelProvider(fragment);
}

Es nimmt Fragmentals Argument, erstellt ein ViewModelProviderObjekt und übergibt das Fragment direkt an den ViewModelProviderKonstruktor.

Wir können den gleichen Weg auch verwenden.

ZB vorher:

OurViewModel mOurViewModel = ViewModelProviders.of(this).get(OurViewModel.class);

Nach dem:

OurViewModel mOurViewModel = new ViewModelProvider(this).get(OurViewModel.class);
Hayk Mkrtchyan
quelle
Wenn Sie eine Factory implementieren, haben Sie einen anderen Weg: Sie haben ViewModelProvidereinen Konstruktor, der sowohl a ViewModelStoreOwnerals auch a erwartet Factory.
Russellhoff
3

Ich bin kein Experte, aber ich habe eine Codezeile, die mein Problem in Java gelöst hat. Hoffe das hilft jemandem.

viewModel = 
new ViewModelProvider
.AndroidViewModelFactory(getApplication())
.create(ViewModel.class);

Wie gesagt, ich würde gerne mehr Details liefern, aber dies hat dieses Problem für mich behoben.

ZeePee
quelle
Dieser Code ist falsch, onCleared()wird nicht auf diese Weise aufgerufen und Ihr ViewModel wird jedes Mal neu erstellt (nicht für Konfigurationsänderungen aufbewahrt).
EpicPandaForce
Können Sie anhand eines bestimmten Beispiels etwas mehr erklären, was meinen Fehler beheben würde? Bitte fügen Sie einen Verweis auf die Erklärung oder etwas ein, das die Dinge klarer machen würde
ZeePee
viewModel = new ViewModelProvider(this).get(MyViewModel.class). Wenn Sie AndroidViewModeldas nicht bekommen Application, haben Sie eine Versionsinkongruenz zwischen Lebenszyklus und Aktivität / Fragment.
EpicPandaForce
Ok, also ist es falsch, getApplicationContext aufzurufen? Sollte es nur getContext sein?
ZeePee
1
Das Problem ist das Erstellen eines new ViewModelProvider.AndroidViewModelFactory(anstelle eines new ViewModelProvider(.
EpicPandaForce
3

Benutze das:

YourViewModel yourViewModel = new ViewModelProvider.AndroidViewModelFactory(getApplication()).create(YourViewModel.class);
Nirwal
quelle
2

Sie können dies stattdessen verwenden:

viewModel= ViewModelProvider(this).get(YourViewModel::class.java)

"this" in den Klammern ist der Eigentümer der YourViewModel-Instanz.

Amin
quelle
1

Diese Antwort ist für Java, aber Sie können den Hauptpunkt verstehen. Die Lösung besteht darin, dass Sie ViewModelProvider verwenden müssen, da ViewModelProviders veraltet sind :

//Do not forget import it.
import androidx.lifecycle.AndroidViewModel;

ViewModelProvider.AndroidViewModelFactory(getApplication()).create(YourViewModel.class);

Beispiel für die Verwendung ist:

YourViewModel yourViewModel = new ViewModelProvider.AndroidViewModelFactory(getApplication()).create(YourViewModel.class);

Vergessen Sie auch nicht, Gradle-Abhängigkeiten zu aktualisieren : Suchen Sie hier nach den letzten Versionen

implementation 'androidx.lifecycle:lifecycle-viewmodel:2.2.0'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.2.0'

!!! Seien Sie jedoch vorsichtig, da einige Antworten diese Lösung empfehlen, sie jedoch bei mir nicht funktioniert hat:

yourViewModel = new ViewModelProvider(this).get(YourViewModel.class);

Denn als ich diesen Weg benutzte, kam ich unter die Fehlermeldung:

Auslöser: java.lang.RuntimeException: Es kann keine Instanz der Klasse com.canerkaseler.mvvmexample.ViewModel erstellt werden

@canerkaseler

canerkaseler
quelle
Diese Antwort ist falsch. Sie müssen die Factory an einen ViewModelProvider übergeben. Wenn Sie direkt aufrufen create, onCleared()funktioniert dies nicht richtig.
EpicPandaForce
Tatsächlich haben Sie buchstäblich nur gesagt, dass Sie nicht die richtige Antwort verwenden sollen. Klingt so, als hätten Sie ein Missverhältnis zwischen Ihren androidx.coreund Ihren androidx.lifecycleAbhängigkeiten.
EpicPandaForce
Normalerweise habe ich die Factory an ViewModelProvider geschrieben. Sie haben es jedoch gelöscht. ContactViewModel contactViewModel = neuer ViewModelProvider.AndroidViewModelFactory (getApplication ()). Create (ContactViewModel.class); Warum hast du es in meiner Antwort gelöscht? Sie haben falsche Codes übergeben.
canerkaseler
0

Wenn Sie Dolch verwenden, passieren Sie die Fabrik im Konstruktor

  MobileViewModel mobileViewModel = new ViewModelProvider(this,providerFactory).get(MobileViewModel.class);
Apoorv Vardhman
quelle
-2

Wenn Sie diese Implementierung haben

'implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

Versuchen zu benutzen viewModel = MainViewModel()

Eddy Yoel Fresno Hernández
quelle
Dies ist keine Möglichkeit, ein Ansichtsmodell zu instanziieren. Sie müssen dafür die ViewModelProvider-Klasse verwenden
Emmanuel Mtali
-2

Versuche dies...

 LocationViewModel locationViewModel = new ViewModelProvider(this).get(LocationViewModel.class);
Shrawan
quelle
-5

es sollte so funktionieren

 viewModel = ViewModelProviders.of(this@MainActivity).get(MainActivityViewModel::class.java)
Hamdi Hanbali
quelle
1
Während Ihre Code-Instanz die Klasse ist, wird keine Verbindung zu dem Ansichtsstatus hergestellt, der erforderlich ist, damit die View Model-Klasse korrekt auf Lebenszyklusereignisse reagiert. Sie müssen View Models auf die richtige Weise instanziieren, damit sie auf die Lebenszyklen ihrer Eltern reagieren und diese berücksichtigen. Andernfalls werden sie jedes Mal neu und leer erstellt.
Kenneth Argo
Wie oben vom OP und anderen erwähnt; Die ViewModelProviders-Klasse ist veraltet. Siehe: developer.android.com/reference/androidx/lifecycle/…
Kenneth Argo