How to have generic ViewModel in BaseActivty class

守給你的承諾、 提交于 2021-02-07 20:14:27

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!