如何在BaseActivity类中使用通用ViewModel

问题描述 投票:0回答:3

我希望有一个基本活动类来处理我开始像这样定义它的一些初始化。

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的类型参数。

我该如何实例化它?

android kotlin android-viewmodel kotlin-reified-type-parameters
3个回答
1
投票

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

abstract val viewModelClass: Class<VIEW_MODEL>

我真的不喜欢这样的东西


0
投票

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

protected abstract fun getViewModel(): Class<M>

替换你的行

viewmodel = ViewModelProviders.of(this).get(getViewModel())

希望它会起作用。


0
投票

第一种方法在Base Activity中制作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>
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.