如何在BaseActivty类中具有通用ViewModel

时间:2019-03-21 21:12:57

标签: android kotlin android-viewmodel kotlin-reified-type-parameters

我想拥有一个基础活动类,该类负责一些初始化工作,我开始像这样定义它。

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
    }
}

但是我收到此错误

  

不能将“ VIEW_MODEL”用作类型化参数。改用课程

我应该如何解决此问题,我想在其中将ViewModel的类型定义为BaseActivity的类型化参数。

该如何实例化它?

3 个答案:

答案 0 :(得分:1)

一种解决方案是拥有这样的东西

abstract val viewModelClass: Class<VIEW_MODEL>

我真的很想不要这样的东西

答案 1 :(得分:0)

@svkaka已经提到了一种解决方案。创建一个抽象方法,并用您的ViewModel类覆盖它:

protected abstract fun getViewModel(): Class<M>

替换行
viewmodel = ViewModelProviders.of(this).get(getViewModel())

希望它会起作用。

答案 2 :(得分:0)

  

第一种方法在基本活动中创建abstarct方法。这样,您必须在所有活动中覆盖abstarct方法。

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()
        }
    }
  

当您在活动中覆盖此方法时

 override fun getViewModel(): MyProfileViewModel {
        mMyProfileViewModel = ViewModelProviders.of(this, mViewModelFactory).get(MyProfileViewModel::class.java)
        return mMyProfileViewModel
    }
  

第二种方法

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>
    }
}