问题
I want to have a base activity class that takes care of some initialization I started defining it like this.
abstract class BaseActivity<VIEW_MODEL : ViewModel, BINDING : ViewDataBinding> :
AppCompatActivity() {
lateinit var viewmodel: VIEW_MODEL
lateinit var binding: BINDING
lateinit var glide: RequestManager
@get:LayoutRes
abstract val layoutResource: Int
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, layoutResource)
viewmodel = ViewModelProviders.of(this).get(VIEW_MODEL::class.java)
^^^^^^^^^^^^^^^^^
this is causing error
}
}
But I am getting this error
Cannot use 'VIEW_MODEL' as reified type parameter. Use a class instead
How should I solve this problem, where I want to define the type of ViewModel as typed parameter of BaseActivity.
And how can I instantiate it?
回答1:
one solution is to have something like this
abstract val viewModelClass: Class<VIEW_MODEL>
I would really like not to have something like this
回答2:
1st way Make abstarct method in Base Activity.In this way you have to override abstarct method in all activity.
abstract class BaseActivity< ViewModel : BaseViewModel,Binding : ViewDataBinding> : AppCompatActivity(){
protected lateinit var binding: Binding
private var mViewModel: V? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
performViewModelBinding()
}
@LayoutRes
abstract fun getLayoutResId(): Int
abstract fun getViewModel(): ViewModel
private fun performViewModelBinding() {
binding = DataBindingUtil.setContentView(this, getLayoutResId())
this.mViewModel = mViewModel ?: getViewModel()
binding.setVariable(BR.viewModel, mViewModel)
binding.executePendingBindings()
}
}
And when you override this method in activity
override fun getViewModel(): MyProfileViewModel {
mMyProfileViewModel = ViewModelProviders.of(this, mViewModelFactory).get(MyProfileViewModel::class.java)
return mMyProfileViewModel
}
2nd way you can do this
abstract class BaseActivity<VIEW_MODEL : ViewModel, BINDING : ViewDataBinding> :
AppCompatActivity() {
lateinit var viewmodel: VIEW_MODEL
lateinit var binding: BINDING
lateinit var glide: RequestManager
@get:LayoutRes
abstract val layoutResource: Int
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, layoutResource)
viewmodel = ViewModelProviders.of(this).get(getViewModelClass())
}
private fun getViewModelClass(): Class<VIEW_MODEL> {
val type = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] // index of 0 means first argument of BaseActivity class param
return type as Class<VIEW_MODEL>
}
}
来源:https://stackoverflow.com/questions/55289334/how-to-have-generic-viewmodel-in-baseactivty-class