【问题标题】:Getting generic class from Kotlin Generic从 Kotlin Generic 获取泛型类
【发布时间】:2018-06-04 09:12:42
【问题描述】:

我有以下类签名:

abstract class BaseActivity<E : ViewModel> : AppCompatActivity() {

    protected lateinit var viewModel: E

}

现在我想使用 ViewModelProvider 以通用方式初始化我的 viewModel,所以:

   viewModel = ViewModelProviders.of(this, viewModelFactory)
            .get(MyViewModel::class)

鉴于 MyViewModel 类将以泛型类型提供,我想说这可能会被抽象到 BaseActivity 中,因此我不必为扩展它的每个 Activity 都这样做。

我试过了:

inline fun <reified E : ViewModel> getViewModelClass() = E::class.java

但是在做的时候:

viewModel = ViewModelProviders.of(this, viewModelFactory)
            .get(getViewModelClass())

我收到Cannot use E as reified type paramter. Use class instead

有解决办法吗?

【问题讨论】:

    标签: android kotlin


    【解决方案1】:

    BaseActivity 中的E 不能是reified,因此您不能将其传递给任何采用reified E 的方法。

    您最好的选择可能就是接受该类作为构造函数参数。

    abstract class BaseActivity<E : ViewModel>(private val modelClass: Class<E>) : AppCompatActivity() {
    
        protected lateinit var viewModel: E
    
        ... viewModel = ViewModelProviders.of(this, viewModelFactory)
            .get(modelClass)
    }
    

    如果BaseActivity 不是抽象的,你可以添加一个工厂方法:

    // outside BaseActivity class itself
    fun <reified E : BaseModel> BaseActivity() = BaseActivity(E::class.java)
    

    但在扩展它时无济于事。

    【讨论】:

      【解决方案2】:

      你可以这样做:

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

      现在,您可以从 BaseActivity 扩展任何类并覆盖返回相应 ViewModel 类的 getViewModel() 函数。

      希望这会有所帮助。

      编辑

      试试这个:

       inline fun <reified E> getViewModelClass(): Class<E> {
          return E::class.java
      }
      

      并像这样使用它:

      viewModel = ViewModelProviders.of(this, viewModelFactory)
              .get(getViewModelClass())
      

      【讨论】:

      • 这仍然迫使我在子类上实现样板。虽然这是一个改进
      • 您在使用上面提到的内联函数 getViewModelClass() 时是否遇到任何错误?
      • 是的,Cannot use E as reified type paramter. Use class instead
      • 你能试试编辑答案吗?
      【解决方案3】:

      https://stackoverflow.com/a/52107111/8832537

      你应该检查一下这个人的解决方案。他的方法的唯一缺点是他使用反射 API 来获取通用参数。我进行了很多研究,但没有找到不使用反射的解决方案。如果你找到了,请告诉我。那样会更方便。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-26
        相关资源
        最近更新 更多