ViewModelProviders è obsoleto in 1.1.0


148

Guardando i documenti di Google per ViewModel, mostrano il seguente codice di esempio su come ottenere un ViewModel:

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

Quando si utilizza l'ultima dipendenza android.arch.lifecycle:extensions:1.1.1non esiste tale classe ViewModelProviders.

Andando alla documentazione per ViewModelProviders, ho visto un commento che diceva:

Questa classe è stata deprecata nel livello API 1.1.0. Utilizzare ViewModelProvider.AndroidViewModelFactory

Il problema è che, quando si tenta di utilizzare ViewModelProvider.AndroidViewModelFactory, non è possibile trovare un ofmetodo equivalente per ottenere l'istanza di ViewModel.

Cosa ho provato a fare:

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

Da qui il nome del metodo create, ottengo una nuova istanza di ViewModel ogni volta che lo chiamo, che non è quello che sto cercando.

Qualche idea su come sostituire il codice obsoleto sopra?


usa il modello singleton o passa ad AndroidX
Oussema Aroua il

Risposte:


31

AGGIORNAMENTO 2020-06-16 : Attualmente ViewModelProviders è obsoleto e non dovrebbe più essere utilizzato. Questa domanda e risposta risalgono alla fine del 2018, quando non era così. Questa domanda e risposta valgono anche per l'edizione precedente di Architecture Components ViewModelProviders, non per l'edizione AndroidX.


Quando si utilizza l'ultima dipendenza android.arch.lifecycle:extensions:1.1.1non esiste tale classe ViewModelProviders.

Si C'è. Per dimostrarlo:

  • Crea un nuovo progetto in Android Studio 3.2.1 (con Kotlin, minSdkVersion21, modello "attività vuota")

  • Aggiungi android.arch.lifecycle:extensions:1.1.1alle dipendenze del appmodulo

Questo ti darà un app/build.gradlelike:

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

Vedrai quindi che la libreria apparirà in "Librerie esterne" con quella classe:

Librerie esterne

E sarai in grado di fare riferimento a quella classe:

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

Passando alla documentazione di ViewModelProviders, ho visto un commento che diceva: questa classe era obsoleta nel livello API 1.1.0. Utilizzare ViewModelProvider.AndroidViewModelFactory

Tale commento si trova sotto la ViewModelProviders.DefaultFactoryvoce della classe e si riferisce a quella classe, non ViewModelProviders:

Schermata della documentazione

Qualche idea su come sostituire il codice obsoleto sopra?

Usa ViewModelProviders.


1
@TareKKhoury: Questo lo spiegherebbe! Tenere traccia di quali moduli necessitano di quali dipendenze sicuramente può essere una sfida. Sono felice di sapere che hai funzionato!
CommonsWare il

13
Questo non è più vero, ViewModelProviders.of()non esiste più.
EpicPandaForce

323

Uso la 2.2.0versione delle estensioni del ciclo di vita :

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

Dovrebbe funzionare, usando il ViewModelProvidercostruttore.

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


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

Aggiornamento 2020/5/15

Trovo un altro modo elegante per raggiungere, Android KTX può aiutare

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

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

2020/06/25: corretto il caso del delegato


160
Sono stufo del costante ciclo di "deprezzamento" di Google.
AFD

3
ViewModelProviders.of () è stato deprecato. È possibile passare un frammento o FragmentActivity al nuovo costruttore ViewModelProvider (ViewModelStoreOwner) per ottenere la stessa funzionalità. (aosp / 1009889)
Raghu Krishnan R

31
Equivalente a Java:YourViewModel viewModel = new ViewModelProvider(this).get(YourViewModel.class);
divieto di geoingegneria dal

16
Mi preoccupo se un giorno Google deprezzerà TextViewo EditTexte introdurrà un nuovo componente.
Pranjal Choladhara,

4
androidx lifecycle-viewmodel 2.1.0 non ha un costruttore senza una factory. usare semplicemente (questo) non funziona. ViewModelProvider (ViewModelStoreOwner, Factory) e ViewModelProvider (ViewModelStore, Factory) sono gli unici costruttori
DevinM

70

Come menzionato da @FantasyFang nella sua risposta, usa l'ultima versione per quella lifecycle:lifecycle-extensionsche è in questo momento 2.2.0-alpha03. Quindi dovresti aggiungere nel tuo file build.gradle la seguente riga:

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

Per coloro che utilizzano Java, per risolvere questo problema, passare tali argomenti direttamente al costruttore di ViewModelProvider :

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

O se non usi una fabbrica, usa semplicemente:

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

Senza passare l'oggetto di fabbrica.


1
Dovresti usare quanto segue in build.gradle: implementazione "androidx.lifecycle: lifecycle-viewmodel: $ lifecycle_version" Come notato in developer.android.com/jetpack/androidx/releases/lifecycle Le API nelle estensioni del ciclo di vita sono state deprecate. Invece, aggiungi dipendenze per gli specifici artefatti del ciclo di vita di cui hai bisogno.
Kenneth Argo,

40

A partire dalla 2.2.0. le estensioni del ciclo di vita sono state deprecate. Fare riferimento alla documentazione di Google .

Questo è il taglio dalla pagina:

Le API nelle estensioni del ciclo di vita sono state deprecate. Invece, aggiungi dipendenze per gli specifici artefatti del ciclo di vita di cui hai bisogno.

Le nuove librerie sono:

// 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}"

Il nuovo codice per JAVA:

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

O per Kotlin:

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

Manteniamo l'istanza di ViewModelProvider o dobbiamo ricrearla di nuovo, nel qual caso verranno distrutte anche tutte le istanze sottostanti. Non ho il motivo di ricrearlo se l'idea è di guardare il ciclo di vita del frammento / attività
TheRealChx101

31

Obsoleto da: ViewModelProviders.of(this, provider).get(VM::class.java)

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


4
esattamente quello che stavo cercando.
Rahul Bali,

21

All'inizio del 2020, Google ha deprecato la classe ViewModelProviders , nella versione 2.2.0 della libreria del ciclo di vita di androidx.

Non è più necessario utilizzare ViewModelProviders per creare un'istanza di ViewModel, è possibile invece passare l'istanza Fragment o Activity al costruttore ViewModelProvider.

Se usi il codice come:

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

riceverai un avviso che ViewModelProviders è stato deprecato.

Per evitare l'uso di librerie obsolete, apportare le seguenti modifiche:

  1. Nel file build.gradle (Modulo: app), utilizzare la versione 2.2.0 dei componenti del ciclo di vita:

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

    Se invece si desidera utilizzare ViewModel da un frammento, utilizzare

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

    fragment-ktx include automaticamente activity-ktx, quindi non è necessario specificare entrambe le dipendenze.

  2. Devi specificare Java 8 nella sezione android:

    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. Nel tuo frammento o attività, modifica l'importazione in:

    import androidx.activity.viewModels

  4. Il codice per creare un ViewModel diventa quindi:

    val viewModel: CalculatorViewModel by viewModels()

    invece di

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

    Utilizzare l'oggetto viewModel come:

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

    dove newNumer è un oggetto LiveData

    In un frammento che desideri condividere il ViewModel dell'attività, utilizzeresti

    val viewModel: CalculatorViewModel by activityViewModels()

Questo è l'equivalente del passaggio dell'istanza Activity nella ViewModelProviders.of()funzione (obsoleta) .


17

ViewModelProviders.of () è stato deprecato. inserisci qui la descrizione dell'immagine

Utilizzare direttamente i costruttori ViewModelProvider poiché ora gestiscono il ruolo ViewModelProvider.Factory predefinito.

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

13

Sì @Tarek, è obsoleto. Utilizza ora con AndroidX:

val yourViewModel = ViewModelProvider.NewInstanceFactory().create(YourVideoModel::class.java)

5
Questa risposta è sbagliata Dovresti usare un ViewModelProvider(viewModelStoreOwner, factory).get(YourVideoModel::class.java)altrimenti il ​​tuo onCleared()non funzionerà correttamente e ViewModel non verrà mantenuto attraverso la modifica della configurazione. Non usare questa risposta.
EpicPandaForce

13

Probabilmente puoi semplicemente usare:

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

senza bisogno di aggiungere android.arch.lifecycle:extensions:1.1.1come dipendenza.



8

Sto usando android Xe ho avuto anche questo problema.

Prima di tutto , dovresti aggiungere queste dipendenze al tuo Gradle:

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

Nel mio caso, $ lifecycle_version era 2.2.0-rc02

Secondo: l'importazione per il ViewModelProviderdovrebbe essere:

import androidx.lifecycle.ViewModelProvider

Quindi puoi inizializzare il tuo vIewModel come negli esempi seguenti:

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

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

grazie per la tua risposta, ma quando la uso allora osservi il modello osservi e la mappatura dei campi non funziona più
Mosa

Credo che androidx.lifecycle:lifecycle-compilersia obsoleto androidx.lifecycle:lifecycle-common-java8.
Bink

8

In realtà, cosa fa il ViewModelProviders.of()metodo sotto il cofano?

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

Prende Fragmentcome argomento, crea ViewModelProvideroggetto e passa il frammento direttamente al ViewModelProvidercostruttore.

Possiamo usare anche allo stesso modo.

Ad esempio prima:

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

Dopo:

OurViewModel mOurViewModel = new ViewModelProvider(this).get(OurViewModel.class);

Se implementi una fabbrica, hai un altro modo: ViewModelProviderha un costruttore che si aspetta sia a ViewModelStoreOwnerche a Factory.
Russellhoff,


3

Non sono un esperto, ma ho una riga di codice che ha risolto il mio problema in Java. Spero che questo aiuti qualcuno.

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

Come ho detto, mi piacerebbe fornire maggiori dettagli, ma questo ha risolto questo problema per me.


Questo codice è errato, onCleared()non verrà chiamato in questo modo e ViewModel verrà ricreato ogni volta (non conservato per le modifiche alla configurazione).
EpicPandaForce

Puoi spiegarci un po 'di più con un certo esempio, cosa risolverebbe il mio errore? Per favore, incolla un riferimento alla spiegazione o tutto ciò che renderebbe le cose più chiare
ZeePee

viewModel = new ViewModelProvider(this).get(MyViewModel.class). Se il tuo AndroidViewModelnon ottiene Application, allora hai una discrepanza di versione tra Ciclo di vita e Attività / Frammento.
EpicPandaForce

Ok, quindi chiamare getApplicationContext è sbagliato? Dovrebbe essere solo getContext?
ZeePee

1
Il problema è creare un new ViewModelProvider.AndroidViewModelFactory(anziché un new ViewModelProvider(.
EpicPandaForce

3

Usa questo:

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

2

È possibile utilizzare questo invece:

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

"this" tra parentesi è il proprietario dell'istanza YourViewModel.


1

Questa risposta è per Java ma puoi capire il punto principale. La soluzione è che è necessario utilizzare ViewModelProvider perché ViewModelProviders è obsoleto :

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

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

Esempio di utilizzo è:

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

Inoltre, non dimenticare l'aggiornamento delle dipendenze dei gradi : controlla qui per le ultime versioni di essi

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

!!! Tuttavia, fai attenzione perché alcune risposte raccomandano questa soluzione ma non ha funzionato per me:

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

Perché quando ho usato in questo modo, sono arrivato sotto il messaggio di errore:

Causato da: java.lang.RuntimeException: impossibile creare un'istanza della classe com.canerkaseler.mvvmexample.ViewModel

@canerkaseler


Questa risposta è sbagliata È necessario passare la fabbrica a ViewModelProvider. Se invochi direttamente create, onCleared()non funzionerà correttamente.
EpicPandaForce

In effetti, hai letteralmente detto di non usare la risposta corretta. Sembra che tu abbia avuto una discrepanza tra la tua androidx.coree le tue androidx.lifecycledipendenze.
EpicPandaForce

Normalmente ho scritto la fabbrica su ViewModelProvider. Tuttavia, l'hai eliminato. ContactViewModel contactViewModel = new ViewModelProvider.AndroidViewModelFactory (getApplication ()). Create (ContactViewModel.class); Perché l'hai eliminato sulla mia risposta? Hai passato codici errati.
canerkaseler

0

Quando usi il pugnale, passerai alla fabbrica nel costruttore

  MobileViewModel mobileViewModel = new ViewModelProvider(this,providerFactory).get(MobileViewModel.class);

-2

Se hai questa implementazione

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

Prova ad usare viewModel = MainViewModel()


Questo non è un modo per creare un'istanza di un modello di vista. È necessario utilizzare la classe ViewModelProvider per questo
Emmanuel Mtali

-2

Prova questo...

 LocationViewModel locationViewModel = new ViewModelProvider(this).get(LocationViewModel.class);

-5

dovrebbe funzionare in questo modo

 viewModel = ViewModelProviders.of(this@MainActivity).get(MainActivityViewModel::class.java)

1
Mentre il tuo codice potrebbe essere un'istanza, la classe non creerà la connessione allo stato di visualizzazione richiesto per avere la classe Visualizza modello per rispondere correttamente agli eventi del ciclo di vita. È necessario istanza Visualizza modelli nel modo corretto in modo che rispondano e onorino i cicli di vita dei loro genitori, altrimenti devono essere ricreati freschi e vuoti ogni volta.
Kenneth Argo,

Come notato sopra dal PO e altri; la classe ViewModelProviders è stata deprecata. Vedi: developer.android.com/reference/androidx/lifecycle/…
Kenneth Argo il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.