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.