在将项目迁移到Kotlin时,我表现出奇怪的行为。
这是在我尝试生成匕首注射器时发生的。 Java或Dagger中的问题,某人无法从通用类型解析Kotlin List
示例:
interface CacheEntity<Result> {
fun onResult(result: Result)
fun getUpdatableData(): Observable<Result>
}
class CacheRepository< Result, Entity:CacheEntity<Result> >(
val entity: Entity) {
// do some operations with Entity
fun doSome() {
entity.getUpdatableData()
entity.onResult(...)
}
}
class UserRepository: CacheEntity<User> {
override fun onResult(result: User) {}
override fun getUpdatableData(): Observable<User> {}
}
现在,如果我要创建缓存的用户存储库实例,一切正常然后此代码使用匕首注入转换为应用程序
val cachedUserRepo = CacheRepository<User, UserRepository>(UserRepository())
但是!如果我试图得出数据列表
class OrdersRepository: CacheEntity<List<Order>> {
// overrides CacheEntity methods
}
val cachedOrdersRepo = CacheRepository<List<Order>, OrdersRepository>(OrdersRepository())
一切都很好,但是在Dagger生成的Java代码中不是这样:MyComponent.java
private CacheRepository<List<Order>, OrdersRepository> cachedOrdersRepository;
构建时出错
error: type argument OrdersRepository is not within bounds of type-variable Entity
private Provider<CachedRepository<List<Order>, OrdersRepository>> cachedOrdersRepository;
^
where Entity,Result are type-variables:
Entity extends CacheEntity<Result> declared in class CacheRepository
Result extends Object declared in class CacheRepository
Java代码包含与kotlin.collections.List不兼容的java.util.List,但是用kotlin编写的dagger模块类,并返回有效的kotlin kotlin.collections.List
@Module
object RepoModule {
@JvmStatic
@Provides
fun provideCacheOrdersRepository(): CacheRepository<List<Order>, OrdersRepository> {
return CacheRepository(OrdersRepository())
}
}
那么,如何解决这个问题?我有几个主意,但我不喜欢这样:
用Java重写dagger模块,在我转换为Kotlin之前就起作用了
强制使用java.util.List,但这是一个非常糟糕的主意
这与Kotlin列表的字节码转换和签名中添加的通配符有关,使其成为java.util.List<? extends T>
而不是java.lang.List<T>
。
[要在不切换为逆变类型(例如MutableList
)的情况下进行修复,则应在@JvmSuppressWildcards
类型上使用List
:
例如
class OrdersRepository: CacheEntity<List<@JvmSuppressWildcards Order>>
我仅添加了完整代码的一个片段,您应该检查列表的用法并在其上使用@JvmSuppressWildcards
。
[确定,我找到了快速的解决方案:使用MutableList<T>
解决了此问题,并且由于未知原因它与java.util.List<T>
兼容。