【问题标题】:Generic class type usage in KotlinKotlin 中的泛型类类型使用
【发布时间】:2018-06-02 17:31:36
【问题描述】:

我正在尝试编写一个通用的基础活动,它指定它的 ViewModel 类型是一个通用参数:

abstract class BaseActivity<T : ViewModel> : AppCompatActivity()

现在我正在尝试为我的 ViewModel 编写一个惰性初始化属性:

val viewModel by lazy { ViewModelProviders.of(this, getFactory()).get(T) }

显示的错误是Type Parameter T is not an expression

同样使用::class::class.java 也无济于事。谁能解释一下这个问题?

编辑:我尝试使用这样的具体内联函数:

inline fun <reified T : ViewModel?> AppCompatActivity.obtainViewModel(factory: ViewModelProvider.Factory): T {
    return ViewModelProviders.of(this, factory).get(T::class.java)
}

并像这样使用它:

abstract class BaseActivity<T> : AppCompatActivity() {
    val viewModel by lazy { obtainViewModel<T>(getFactory()) 
}

现在我得到错误,T 不能用作具体参数。

EDIT2: 迄今为止最好的解决方案似乎是:Link,但是在每个扩展类中实现抽象标记的开销。

【问题讨论】:

标签: android generics kotlin


【解决方案1】:

你的类有一个类型参数T,不幸的是它在运行时被删除了。结果,调用get(T) 不起作用(我猜该方法实际上需要Class?)。

您似乎已经注意到这一点,因此尝试通过将处理封装到使用 reified 类型的方法中来修复它。但是,您不能将 T 作为具体参数传递,因为在调用 reified-typed 方法时,此类型已被删除。因此,obtainViewModel&lt;T&gt; 也不起作用。您可以做的是,将T 用于普通的泛型方法,如下所示:

class Typed<T> {
    val lazyProp by lazy {
        listOf<T>()
    }
}

【讨论】:

  • 所以没有办法实现我试图实现的行为?
  • 恐怕不是这样。您对我刚刚添加的建议有何看法
  • 感谢您的回答 :) 不幸的是,这会使我试图包装的代码变得比以前更复杂。 ://
  • 你找到其他方法了吗?
  • @ArchieG.Quiñones 不确定您是否找到了解决方案,但请在此处查看我的建议 stackoverflow.com/a/53480529/5315499
【解决方案2】:

可能有点晚了,但我想这可能是实现它的优雅方式:

abstract class BaseActivity<T : ViewModel>(
    private var modelClass: Class<T>) : AppCompatActivity() {

    val viewModel by lazy { 
        ViewModelProviders.of(this, getFactory()).get(modelClass) 
    }

}

然后

class SampleActivity : BaseActivity<SampleViewModel>(SampleViewModel::class.java) {
    // use viewModel from here
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    • 2021-09-21
    • 2018-09-29
    • 2017-06-25
    相关资源
    最近更新 更多