Reputation: 4074
I have the following class signature:
abstract class BaseActivity<E : ViewModel> : AppCompatActivity() {
protected lateinit var viewModel: E
}
Now I want to initialize my viewModel in a generic way using ViewModelProvider, so:
viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(MyViewModel::class)
Given that MyViewModel class will be provided in the generic type, I'd say this could potentially be abstracted into the BaseActivity so I dont have to do it for every Activity that extends it.
I tried with:
inline fun <reified E : ViewModel> getViewModelClass() = E::class.java
But then when doing:
viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(getViewModelClass())
I get Cannot use E as reified type paramter. Use class instead
Is there a solution to this?
Upvotes: 0
Views: 1485
Reputation: 1555
https://stackoverflow.com/a/52107111/8832537
You should check this guy's solution. The only downside of his approach is he uses Reflection API to get the generic parameter. I researched a lot but didn't find a solution that doesn't use reflection. If you did find it, let me know. That would be more convenient.
Upvotes: 1
Reputation: 170713
E
in BaseActivity
can't be reified
, so you can't pass it to any methods which take a reified E
.
Your best option may just be to accept the class as a constructor parameter.
abstract class BaseActivity<E : ViewModel>(private val modelClass: Class<E>) : AppCompatActivity() {
protected lateinit var viewModel: E
... viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(modelClass)
}
If BaseActivity
wasn't abstract, you could add a factory method:
// outside BaseActivity class itself
fun <reified E : BaseModel> BaseActivity() = BaseActivity(E::class.java)
but it wouldn't help when extending it.
Upvotes: 3
Reputation: 763
You ca do it in this way:
abstract class BaseActivity<E : ViewModel> : AppCompatActivity() {
protected lateinit var viewModel: E
abstract fun getViewModel():E
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(getViewModel())
}
}
Now, you can extend any class from BaseActivity and override the getViewModel() function returning the respective ViewModel class.
Hope this helps.
EDIT
Try this once:
inline fun <reified E> getViewModelClass(): Class<E> {
return E::class.java
}
and use it like this:
viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(getViewModelClass())
Upvotes: 1