ViewModelProviders está en desuso en 1.1.0

148

En cuanto a los documentos de Google para ViewModel, muestran el siguiente código de ejemplo sobre cómo conseguir una ViewModel:

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

Cuando se usa la última dependencia android.arch.lifecycle:extensions:1.1.1no existe tal clase ViewModelProviders.

Ir a la documentación para ViewModelProviders, vi un comentario diciendo:

Esta clase quedó en desuso en el nivel API 1.1.0. Utilice ViewModelProvider.AndroidViewModelFactory

El problema es que, al intentar usarlo ViewModelProvider.AndroidViewModelFactory, no puede encontrar un ofmétodo equivalente para obtener la instancia de ViewModel.

Lo que intenté hacer:

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

De ahí el nombre del método create, obtengo una nueva instancia del ViewModel cada vez que lo llamo, que no es lo que busco.

¿Alguna idea de cuál es el reemplazo del código en desuso anterior?

TareK Khoury
fuente
use el patrón singleton o cambie a AndroidX
Oussema Aroua

Respuestas:

31

ACTUALIZACIÓN 2020-06-16 : Actualmente ViewModelProviders está en desuso y ya no debe usarse. Esta pregunta y respuesta fueron de fines de 2018, cuando ese no era el caso. Esta pregunta y respuesta también son para la edición anterior de Architecture Components ViewModelProviders, no para la edición de AndroidX.


Cuando se usa la última dependencia android.arch.lifecycle:extensions:1.1.1no existe tal clase ViewModelProviders.

Sí hay. Para demostrar esto:

  • Cree un nuevo proyecto en Android Studio 3.2.1 (con Kotlin, minSdkVersion21, plantilla de "actividad vacía")

  • Agregar android.arch.lifecycle:extensions:1.1.1a las dependencias del appmódulo

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

Luego verá que la biblioteca aparece en "Bibliotecas externas" con esa clase:

Bibliotecas externas

Y podrás hacer referencia a esa clase:

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

Al ir a la documentación de ViewModelProviders, vi un comentario que decía: Esta clase fue obsoleta en el nivel de API 1.1.0. Utilice ViewModelProvider.AndroidViewModelFactory

Ese comentario está debajo de la ViewModelProviders.DefaultFactoryentrada de clase y se refiere a esa clase, no a ViewModelProviders:

Captura de pantalla de documentación

¿Alguna idea de cuál es el reemplazo del código en desuso anterior?

Uso ViewModelProviders.

CommonsWare
fuente
1
@TareKKhoury: ¡Eso lo explicaría! Hacer un seguimiento de qué módulos necesitan qué dependencias definitivamente puede ser un desafío. ¡Me alegra saber que lo tienes funcionando!
CommonsWare
13
Esto ya no es cierto, ViewModelProviders.of()ya no existe.
EpicPandaForce
323

Yo uso la 2.2.0versión de extensiones de ciclo de vida :

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

Debería ser trabajo, utilizando ViewModelProviderconstructor.

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


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

Actualización 2020/5/15

Encuentro otra forma elegante de lograrlo, Android KTX puede ayudar

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

2020/06/25: corrigió el caso del delegado

Colmillo de fantasía
fuente
160
Estoy un poco harto del constante ciclo de "depreciación" de Google.
AFD
3
ViewModelProviders.of () ha quedado en desuso. Puede pasar un Fragment o FragmentActivity al nuevo constructor ViewModelProvider (ViewModelStoreOwner) para lograr la misma funcionalidad. (aosp / 1009889)
Raghu Krishnan R
31
Equivalente en Java:YourViewModel viewModel = new ViewModelProvider(this).get(YourViewModel.class);
suspensión de la geoingeniería
16
Me preocupa si algún día Google desaprobará TextViewo EditTextintroducirá un nuevo componente.
Pranjal Choladhara
44
androidx lifecycle-viewmodel 2.1.0 no tiene un constructor sin una fábrica. usando simplemente (esto) no funciona. ViewModelProvider (ViewModelStoreOwner, Factory) y ViewModelProvider (ViewModelStore, Factory) son los únicos constructores
DevinM
70

Como @FantasyFang mencionó en su respuesta, use la última versión para la lifecycle:lifecycle-extensionsque es en este momento 2.2.0-alpha03. Por lo tanto, debe agregar en su archivo build.gradle la siguiente línea:

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

Para aquellos que usan Java, para resolver esto, pase esos argumentos directamente al constructor de ViewModelProvider :

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

O si no usa una fábrica, simplemente use:

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

Sin pasar su objeto de fábrica.

Alex Mamo
fuente
1
Debería utilizar lo siguiente en build.gradle: implementación "androidx.lifecycle: lifecycle-viewmodel: $ lifecycle_version" Como se indica en developer.android.com/jetpack/androidx/releases/lifecycle Las API en las extensiones de ciclo de vida han quedado en desuso. En su lugar, agregue dependencias para los artefactos específicos del ciclo de vida que necesita.
Kenneth Argo
40

A partir de 2.2.0. las extensiones de ciclo de vida han quedado en desuso. Consulte la documentación de Google .

Este es el corte de la página:

Las API en las extensiones de ciclo de vida han quedado en desuso. En su lugar, agregue dependencias para los artefactos específicos del ciclo de vida que necesita.

Las nuevas bibliotecas son:

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

El nuevo código para JAVA:

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

O para Kotlin:

viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
Kenneth Argo
fuente
¿Mantenemos la identidad de ViewModelProvider o tenemos que volver a crearla, en cuyo caso, todas las instancias subyacentes también se destruirán. No tengo la razón de volver a crearlo si la idea es ver el ciclo de vida del fragmento / actividad
TheRealChx101
31

En desuso de: ViewModelProviders.of(this, provider).get(VM::class.java)

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

Braian Coronel
fuente
44
Exactamente lo que estaba buscando.
Rahul Bali
21

A principios de 2020, Google ha desaprobado la clase ViewModelProviders , en la versión 2.2.0 de la biblioteca de ciclo de vida de androidx.

Ya no es necesario usar ViewModelProviders para crear una instancia de ViewModel, puede pasar su instancia de Fragmento o Actividad al constructor ViewModelProvider.

Si usa el código como:

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

recibirá una advertencia de que ViewModelProviders ha quedado en desuso.

Para evitar el uso de bibliotecas obsoletas, realice los siguientes cambios:

  1. En el archivo build.gradle (Módulo: aplicación), use la versión 2.2.0 de los componentes del ciclo de vida:

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

    Si en su lugar desea usar ViewModel desde un Fragmento, use

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

    fragment-ktx incluye automáticamente activity-ktx, por lo que no necesita especificar ambos en las dependencias.

  2. Debe especificar Java 8 en la sección de 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. En su Fragmento o Actividad, cambie la importación a:

    importar androidx.activity.viewModels

  4. El código para crear un ViewModel se convierte en:

    val viewModel: CalculatorViewModel by viewModels()

    en vez de

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

    Utilice el objeto viewModel como:

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

    donde newNumer es un objeto LiveData

    En un fragmento que desea compartir el modelo de vista de la actividad, usaría

    val viewModel: CalculatorViewModel by activityViewModels()

Eso es equivalente a pasar la instancia de Activity en la función (en desuso) ViewModelProviders.of().

kgandroid
fuente
17

ViewModelProviders.of () ha quedado en desuso. ingrese la descripción de la imagen aquí

Utilice los constructores ViewModelProvider directamente ya que ahora manejan el rol predeterminado de ViewModelProvider.Factory.

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

Sí @Tarek, está en desuso. Úselo ahora con AndroidX:

val yourViewModel = ViewModelProvider.NewInstanceFactory().create(YourVideoModel::class.java)
Paulo Linhares - Packapps
fuente
55
Esta respuesta es incorrecta. De lo ViewModelProvider(viewModelStoreOwner, factory).get(YourVideoModel::class.java)contrario, debería usar un onCleared()no funcionará correctamente, y ViewModel no se mantendrá durante el cambio de configuración. No uses esta respuesta.
EpicPandaForce
13

Probablemente puedas usar:

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

sin necesidad de agregar android.arch.lifecycle:extensions:1.1.1como la dependencia.

xiaoyu
fuente
8

Estoy usando android Xy también tuve este problema.

En primer lugar , debe agregar estas dependencias a su Gradle:

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

En mi caso, la versión $ lifecycle_version fue 2.2.0-rc02

Segundo: la importación para el ViewModelProviderdebe ser:

import androidx.lifecycle.ViewModelProvider

Luego puede inicializar su vIewModel como en los ejemplos a continuación:

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

val viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
Igor Fridman
fuente
gracias por su respuesta, pero cuando la uso, viewmodel, observar y campos, la vinculación de datos ya no funciona
Mosa
Creo que androidx.lifecycle:lifecycle-compilerestá obsoleto por androidx.lifecycle:lifecycle-common-java8.
Bink
8

En realidad, ¿qué hace el ViewModelProviders.of()método debajo del capó?

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

Toma Fragmentcomo argumento, crea un ViewModelProviderobjeto y pasa el fragmento directamente al ViewModelProviderconstructor.

Podemos usar la misma manera también.

Ej. Antes:

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

Después:

OurViewModel mOurViewModel = new ViewModelProvider(this).get(OurViewModel.class);
Hayk Mkrtchyan
fuente
Si implementa una Fábrica, tiene otra forma: ViewModelProvidertiene un constructor que espera tanto a ViewModelStoreOwnercomo a Factory.
russellhoff
3

No soy un experto, pero tengo una línea de código que resolvió mi problema en Java. Espero que esto ayude a alguien.

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

Como dije, me encantaría proporcionar más detalles, pero esto solucionó este problema para mí.

ZeePee
fuente
Este código es incorrecto, onCleared()no se llamará de esta manera y su ViewModel se volverá a crear cada vez (no se guarda para los cambios de configuración).
EpicPandaForce
¿Puedes explicar un poco más con un cierto ejemplo, qué solucionaría mi error? Por favor, pegue una referencia a la explicación o cualquier cosa que aclare las cosas
ZeePee
viewModel = new ViewModelProvider(this).get(MyViewModel.class). Si AndroidViewModelno obtiene el Application, entonces tiene una versión que no coincide entre Lifecycle y Activity / Fragment.
EpicPandaForce
Ok, ¿entonces llamar a getApplicationContext está mal? ¿Debería ser solo getContext?
ZeePee
1
El problema es crear un en new ViewModelProvider.AndroidViewModelFactory(lugar de un new ViewModelProvider(.
EpicPandaForce
3

Utilizar este:

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

Puedes usar esto en su lugar:

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

"this" entre paréntesis es el propietario de la instancia de YourViewModel.

Amin
fuente
1

Esta respuesta es para Java pero puedes entender el punto principal. Solución es que usted necesita el uso ViewModelProvider porque ViewModelProviders en desuso :

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

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

El uso de ejemplo es:

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

Además, no olvide actualizar las dependencias de Gradle : consulte aquí las últimas versiones de ellas

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

!!! Sin embargo, tenga cuidado porque algunas respuestas recomiendan esta solución, pero no funcionó para mí:

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

Porque cuando lo usé de esta manera, obtuve el siguiente mensaje de error:

Causado por: java.lang.RuntimeException: no se puede crear una instancia de la clase com.canerkaseler.mvvmexample.ViewModel

@canerkaseler

Canerkaseler
fuente
Esta respuesta es incorrecta. Debe pasar la fábrica a un ViewModelProvider. Si invoca directamente create, onCleared()no funcionará correctamente.
EpicPandaForce
De hecho, literalmente acabas de decir que no uses la respuesta correcta. Parece que tuvo una falta de coincidencia entre usted androidx.corey sus androidx.lifecycledependencias.
EpicPandaForce
Normalmente escribía la fábrica a ViewModelProvider. Sin embargo, lo borraste. ContactViewModel contactViewModel = new ViewModelProvider.AndroidViewModelFactory (getApplication ()). Create (ContactViewModel.class); ¿Por qué lo borraste en mi respuesta? Pasaste códigos incorrectos.
Canerkaseler
0

Cuando uses la daga, pasarás la fábrica en el constructor

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

Si tienes esta implementación

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

Tratar de usar viewModel = MainViewModel()

Eddy Yoel Fresno Hernández
fuente
Esta no es una forma de instanciar un modelo de vista. Debe usar la clase ViewModelProvider para eso
Emmanuel Mtali
-2

Prueba esto...

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

debería funcionar de esta manera

 viewModel = ViewModelProviders.of(this@MainActivity).get(MainActivityViewModel::class.java)
Hamdi Hanbali
fuente
1
Si bien su código crearía una instancia, la clase no creará la conexión con el estado de vista requerido para que la clase Ver modelo responda correctamente a los eventos del ciclo de vida. Debe instanciar Ver modelos de la manera correcta para que respondan y honren los ciclos de vida de sus padres, de lo contrario, se recrearán frescos y en blanco cada vez.
Kenneth Argo
Como se señaló anteriormente por el OP y otros; la clase ViewModelProviders ha quedado en desuso. Ver: developer.android.com/reference/androidx/lifecycle/…
Kenneth Argo