ViewModel
It is used more and more. Strictly speaking, the official does not recommend that you ViewModel
add Context
references to it. At the same time, ViewModel
the construction method does not have any parameters, and sometimes it is very inflexible. Two methods are recorded below.
#1. Through kotlin's extension function
fun <T : ViewModelProvider, V : ViewModel> T.get(
key: String,
modelClass: Class<V>,
context: FragmentActivity
): V {
val model = get(key, modelClass)
if (model is TestViewModel) {
model.addContext(context)
}
return model
}
fun <T : ViewModelProvider, V : ViewModel> T.get(
key: String,
modelClass: Class<V>,
context: Context
): V {
val model = get(key, modelClass)
if (model is TestViewModel) {
model.addContext(context)
}
return model
}
fun <T : ViewModelProvider, V : ViewModel> T.get(
modelClass: Class<V>,
context: FragmentActivity
): V {
val model = get(modelClass)
if (model is TestViewModel) {
model.addContext(context)
}
return model
}
fun <T : ViewModelProvider, V : ViewModel> T.get(
modelClass: Class<V>,
context: Context
): V {
val model = get(modelClass)
if (model is TestViewModel) {
model.addContext(context)
}
return model
}
In the TestViewModel
method, add the following
class TestViewModel : ViewModel() {
protected lateinit var context: Context
open fun addContext(context: FragmentActivity) {
this.context = context
}
open fun addContext(context: Context) {
this.context = context
}
}
Instructions
val viewModel = ViewModelProvider(this).get(TestViewModel::class.java, this)
#2. Through custom ViewModelProvider.Factory
class CoreViewModelFactory(private val context: Context) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
try {
for (constructor in modelClass.constructors) {
if (arrayOf(Context::class.java).contentEquals(constructor.parameterTypes)) {
return (constructor as Constructor<T>).newInstance(context)
}
}
return modelClass.newInstance()
} catch (e: InstantiationException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
} catch (e: IllegalAccessException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
}
}
}
Regarding this one, if you read the code of ViewModelProvider carefully, you will find that there are also two or three kinds of Factory provided. For the context
ones AndroidViewModel
that can be directly owned , they are provided ViewModelProvider.AndroidViewModelFactory
, just don't add them again when you quote them.
Below is yoursTestViewModel
class TestViewModel(private val context: Context) : ViewModel() {
init {
L.i(" context $context ")
}
}
Instructions
val viewModel = ViewModelProvider(this, CoreViewModelFactory(this)).get(TestViewModel::class.java)
The above two methods can also be used to help you customize some of the parameters you want to pass in.