Saltar al contenido

¿Cómo crear una instancia de ViewModel en AndroidX?

Hola, tenemos la solución a tu interrogante, continúa leyendo y la encontrarás un poco más abajo.

Solución:

Respuesta actualizada:

Las cosas cambiaron un poco, ya que la dependencia necesaria anteriormente: ViewModelProviders – quedó obsoleto (consulte la respuesta anterior para obtener más detalles). Ahora puede usar el ViewModelProvider constructor directamente.

Entonces, en este caso, la respuesta sería:

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

Tenga en cuenta que, sin embargo, si incluye el androidx.activity:activity-ktx:$Version dependencia (algunas de las dependencias de AndroidX de uso común ya la incluyen), puede hacer uso de la delegación de propiedades:

private val viewModel: SheduleViewModel by viewModels()

Que utilizará internamente ViewModelProvider y alcance su ViewModel para usted Activity. Es solo una forma más concisa de escribir lo mismo. Puedes hacer lo mismo por un Fragment incluyendo el androidx.fragment:fragment-ktx:$Version dependencia en su lugar (nuevamente, comúnmente ya incluida por otras dependencias de AndroidX).

Ambos ViewModelProvider constructor y by viewModels() también acepta una fábrica como parámetro (útil para inyectar su ViewModel):

private val viewModel = 
    ViewModelProvider(this, viewModelFactory).get(SheduleViewModel::class.java)

y

private val viewModel: SheduleViewModel by viewModels  viewModelFactory 

Utiliza el que mejor se adapte a ti.

Respuesta anterior:

Añade el androidx.lifecycle:lifecycle-extensions:$lifecycleExtensionsVersion dependencia para importar ViewModelProviders.

Actualización de ViewModel a la versión 2.2.0 del ciclo de vida y superior

los ViewModels (VM) teóricamente se pueden inicializar como variables de instancia de nivel de clase utilizando la biblioteca de extensión de Kotlin import androidx.fragment.app.viewModels método by viewmodels(). Al inicializar la VM como una instancia de nivel de clase var, se puede acceder a ella dentro de la clase.

Pregunta: ¿Existe una desventaja de inicializar las VM como variables de instancia de nivel de clase en lugar de dentro onCreate?

Al crear las VM con la función de extensión dentro onCreate las VM solo están dentro del alcance onCreate y se requiere código adicional para reasignar las variables de instancia de nivel de clase.

Ver documentación

  • Descripción general de ViewModel
  • Ciclo vital

Inicializar VM como instancia de clase Val

class Fragment : Fragment() 
    private val viewModel: SomeViewModel by viewModels()

    private fun observeViewState() 
        viewModel.feedViewState.observe(viewLifecycleOwner)  viewState ->
            //viewState used here.
        
    

Inicializar VM en onCreate y reasignar Class Instance Var

class Fragment : Fragment() 
    private lateinit var viewModel: SomeViewModel

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        val viewModel: ContentViewModel by viewModels()
        this.viewModel = viewModel
    

    private fun observeViewState() 
        viewModel.feedViewState.observe(viewLifecycleOwner)  viewState ->
            //viewState used here.
        
    

Pasar argumentos / parámetros

// Override ViewModelProvider.NewInstanceFactory to create the ViewModel (VM).
class SomeViewModelFactory(private val someString: String): ViewModelProvider.NewInstanceFactory() 
    override fun  create(modelClass: Class): T = SomeViewModel(someString) as T
 

class SomeViewModel(private val someString: String) : ViewModel() 
    init 
        //TODO: Use 'someString' to init process when VM is created. i.e. Get data request.
    


class Fragment: Fragment() 
    // Create VM in activity/fragment with VM factory.
    val someViewModel: SomeViewModel by viewModels  SomeViewModelFactory("someString")  

Habilitación de SavedState con argumentos / parámetros

class SomeViewModelFactory(
        private val owner: SavedStateRegistryOwner,
        private val someString: String) : AbstractSavedStateViewModelFactory(owner, null) 
    override fun  create(key: String, modelClass: Class, state: SavedStateHandle) =
            SomeViewModel(state, someString) as T


class SomeViewModel(private val state: SavedStateHandle, private val someString: String) : ViewModel() 
    val feedPosition = state.get(FEED_POSITION_KEY).let  position ->
        if (position == null) 0 else position
    

    init 
        //TODO: Use 'someString' to init process when VM is created. i.e. Get data request.
    

     fun saveFeedPosition(position: Int) 
        state.set(FEED_POSITION_KEY, position)
    


class Fragment: Fragment() 
    // Create VM in activity/fragment with VM factory.
    val someViewModel: SomeViewModel by viewModels  SomeViewModelFactory(this, "someString")  
    private var feedPosition: Int = 0

    override fun onSaveInstanceState(outState: Bundle) 
        super.onSaveInstanceState(outState)
        someViewModel.saveFeedPosition((contentRecyclerView.layoutManager as LinearLayoutManager)
                .findFirstVisibleItemPosition())
        

    override fun onViewStateRestored(savedInstanceState: Bundle?) 
        super.onViewStateRestored(savedInstanceState)
        feedPosition = someViewModel.feedPosition
    

PD. Esto es para alguien que está usando Java y se quedó atascado por un tiempo como lo hice yo y esta respuesta SO aparece en Google todo el tiempo.

Aparentemente, la API ha cambiado a partir de esta fecha (6 de mayo de 2020), tuve que hacer esto para que funcionara.

// 1. Create a ViewModel Class Let's call it AppStateViewModel

// 2. Put below code Inside Activity onCreate like this:
ViewModelProvider.Factory factory = new ViewModelProvider.NewInstanceFactory();
appStateManager = new ViewModelProvider(this, factory).get(AppStateViewModel.class);

Recuerda algo, que tienes la capacidad de agregar una reseña si te fue de ayuda.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *