¿Cómo obtener una instancia de ViewModel en actividad en 2020/21?

3 minutos de lectura

Avatar de usuario de Gerke
Gerke

Soy nuevo en el patrón mvvm. Creé un ViewModel para la actividad principal. Ahora quiero obtener una instancia de ViewModel en la actividad principal.

La mayoría de los tutoriales y respuestas aquí en Stackoverflow sugieren usar ViewModelProviders.of(...pero esto está en desuso.

Entonces, de acuerdo con esta pregunta en stackoverflow: ViewModelProviders está obsoleto en la actividad principal 1.1.0 en onCreate, hago lo siguiente (y podría jurar que ya lo tenía funcionando): mainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);

Sin embargo, recibo un error que me dice que no se ha encontrado un constructor adecuado.

error: no suitable constructor found for ViewModelProvider(MainActivity)

Alternativamente, para dejar absolutamente claro que MainActivity será ViewModelStoreOwner, creé una variable
ViewModelStoreOwner vmso = this; y pon esa variable en el constructor así:
mainActivityViewModel = new ViewModelProvider(vmso).get(MainActivityViewModel.class);

  • ¿Está seguro de su referencia a this ¿es correcto? Si es un Fragmento, deberá usar getActivity() en vez de this iirc, y si estás en una clase de oyente o anónima tendrás que hacer MainActivity@this etcétera etcétera

    – Blundell

    28 de enero de 2020 a las 16:22

  • Estoy llamando al método en onCreate() de la actividad principal

    – Gerke

    28 de enero de 2020 a las 16:48

  • ¿Responde esto a tu pregunta? Como ViewModelProviders.of() está en desuso, ¿cómo debo crear un objeto de ViewModel?

    – Chisko

    30 de enero de 2020 a las 18:14

  • No, no lo hace. La solución descrita en código Java es boardViewModel = new ViewModelProvider(this).get(BoardViewModel.class)que es equivalente a mainActivityViewModel = new ViewModelProvider(this).get(MainActivityViewModel.class); que ya probé, pero parece no ser un constructor adecuado.

    – Gerke

    31 de enero de 2020 a las 15:07


Debe actualizar su archivo gradle a:

implementación ‘androidx.lifecycle:lifecycle-extensions:2.2.0’

Y debido a este cambio, puede pasar Actividad al constructor que mencionó:

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

Usando Fragmento-ktx libr en su aplicación puede obtener viewModel como se muestra a continuación

Primero actualice el archivo Gradle como aplicación -> build.gradle

implementation 'androidx.fragment:fragment-ktx:1.1.0'

// obtener Ver modelo en Actividad o Fragmento como

private val viewModel: MainActivityViewModel by viewModels()

// Si desea obtener la misma instancia de Ver modelo en ChildFragment como

 private val viewModel: MainActivityViewModel by viewModels(
    ownerProducer = { requireParentFragment() }
)

  • Fragment-ktx es para fragmentos. Nosotros necesitamos actividad-ktx

    – Igor Ganapolski

    22 de abril de 2021 a las 1:29

Avatar de usuario de niño
Chico

Usar val viewModel by viewModels<TheViewModel>() en Actividades y val viewModel by activityViewModels<TheViewModel>() en fragmento para obtener el mismo modelo de vista de la actividad (por lo tanto, compartir el modelo de vista).

esto es parte de androidx ahora

  • ¡Gracias! Esto es probablemente obvio para la mayoría de las personas, pero también puede hacer val viewModel: ThisViewModel by viewModels() y val viewModel: ThisViewModel by activityViewModels()

    – elemento eddi

    15 de abril de 2021 a las 2:20

Residencia en Androide documentación, puede hacer esto:

KOTLIN

implementation 'androidx.activity:activity-ktx:1.3.1'

val model: MyViewModel by viewModels()

JAVA

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

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

Obtenga ViewModel de una nueva manera

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

  • Esto es Java. Usamos Kotlin.

    – Igor Ganapolski

    22 de abril de 2021 a las 1:31

Avatar de usuario de Gerke
Gerke

Por ahora, lo único que funcionó para mí fue usar:
MainActivityViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MainActivityViewModel.class);

Sin embargo, todavía estoy agradecido por cualquier consejo, cómo se puede hacer esto de manera diferente usando new ViewModelProvider(this).get(MainActivityViewModel.class);

  • Esto es Java. Usamos Kotlin.

    – Igor Ganapolski

    22 de abril de 2021 a las 1:31

Avatar de usuario de David Buck
David Buck

Puedes usar un ViewModelFactory:

val viewModelFactory = VMFactory(requireActivity().application)
viewModel= ViewModelProvider(requireActivity(),viewModelFactory).get(MainViewModel::class.java)

Código de fábrica VMF:

class VMFactory(application: Application) : ViewModelProvider.NewInstanceFactory() {

    val _application: Application=application

    @NonNull
    override fun <T : ViewModel?> create(@NonNull modelClass: Class<T>): T {
            return  MainViewModel(_application) as T
    }
}

Tenga en cuenta que aquí mi MainViewModel extiende AndroidViewModel y por lo tanto requiere aplicación como parámetro de entrada.

¿Ha sido útil esta solución?