如何将来自 Injekt 库的 injectLazy() 委托与泛型一起使用?

How to use injectLazy() delegate from Injekt library with generics?

我有以下 class 层次结构

interface Presenter

abstract class MvpFragment<P: Presenter> : Fragment() {
    val presenter by injectLazy<P>() // error: Cannot use 'T' as reified type parameter. Use a class instead.
}

有什么方法可以将 injectLazy 委托与泛型一起使用吗?我可以将 KClass<P> 作为参数传递给 MvpFragment,但我仍然不知道如何使用它来注入 P 对象。

编译 Java 代码时,通用类型参数被删除。 Kotlin 提供了一个特性,内联函数可以一直保留这个类型信息到程序的 运行 时间。该功能是 injectLazy<T> 函数用来具体化类型参数的功能。

不过在你的例子中,类型参数 P 来自 class,因此 Kotlin 编译器无法具体化它,这意味着它会在编译为 [=20= 时被删除] 字节码。擦除类型参数后,无法再调用 injectLazy<T> 函数,因为类型信息将在 运行 时丢失。这就是编译器给你错误的原因。

您必须将 KClass<P> 对象传递给您的 class 并使用它来注入依赖项,从而手动具体化类型。

我终于找到了一种方法。但我必须先添加两个新功能:

fun <T: Any> typeRef(type: KClass<T>) = object : TypeReference<T> {
    override val type = type.java
}

fun <T : Any> injectLazy(type: KClass<T>): Lazy<T> {
    return lazy { Injekt.get(forType = typeRef(type)) }
}

现在我可以写了:

abstract class MvpFragment<P : Presenter>(presenterClass: KClass<P>) : Fragment() {
    protected val presenter by injectLazy(type = presenterClass)
}