在 -Kotlin- 中使用 -Dagger- 会遇到的陷阱和优化方法,android 开发实例大全 PDF
@Module
object NetworkModule {
@JvmStatic
@Provides
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder().build()
}
}
复制代码
如果需要使用抽象方法,则需要将 @JvmStatic 添加到 companion object 中,并增加 @Module 注解。
@Module
abstract class NetworkModule {
@Binds abstract fun provideService(retrofitService: RetrofitService): Service
@Module
companion object {
@JvmStatic
@Provides
fun provideOkHttpClient(): OkHttpClient {
return return OkHttpClient.Builder().build()
}
}
}
复制代码
或者,您可以将 object 模块代码抽取出来,并将其包含在抽象模块中:
@Module(includes = [OkHttpClientModule::java])
abstract class NetworkModule {
@Binds abstract fun provideService(retrofitService: RetrofitService): Service
}
@Module
object OkHttpClientModule {
@JvmStatic
@Provides
fun provideOkHttpClient(): OkHttpClient {
return OkHttpClient.Builder().build()
}
}
复制代码
在 Dagger v2.25 版本中,您不再需要使用 @JvmStatic 来标记 @Provides 函数了,Dagger 会正确地识别它。
## 泛型注入
Kotlin 使用通配符编译泛型使 Kotlin API 和 Java 能一起使用。当某个参数或者字段的类型为 [泛型](
) 时,会在 Java 代码中自动生成。比如,Kotlin 的代码 List 参数就会在 Java 中显示为 List<? super Foo>。
但这种特性会导致在 Dagger 中出现问题,因为它期望类型是完全 (也称 invariant) 匹配的。使用?[@JvmSuppressWildcards](
)?将确保 Dagger 会看到没有通配符的类型。
当您使用?[Dagger 的多重绑定特性](
)时,这是一个常常会遇到的问题,比如:
class MyVMFactory @Inject constructor(
private val vmMap: Map<String, @JvmSuppressWildcards
Provider<ViewModel>>
) {
...
}
复制代码
在 Dagger v2.25 版本中,您将不再需要使用 @JvmSuppressWildcards 了,Dagger 会正确地识别它。
## 内联方法体
Dagger 通过检查返回值类型来确定由 @Provides 方法配置的类型。在 Kotlin 函数中的返回类型是可选的,甚至 IDE 有时也会建议您重构代码使用内联方法体来隐藏返回值类型的声明。
如果推断的类型与您所期望的类型不一致,就会引起 bug 出现。我们来看一些例子:
如果要在 Dagger 中添加特定的类型,使用内联将是最好的选择。我们来看看在 Kotlin 中实现同样效果的另外一种方法:
@Provides
fun provideNetworkPrinter() = NetworkPrinter()
@Provides
fun provideNetworkPrinter(): NetworkPrinter = NetworkPrinter()
@Provides
fun provideNetworkPrinter(): NetworkPrinter {
return NetworkPrinter()
}
复制代码
如果您需要提供接口的实现,则必须显示指定返回类型。不这样做的话会出问题:
@Provides
// 配置 Printer
fun providePrinter(): Printer = NetworkPrinter()
@Provides
// 配置 NetworkPrinter,不是一个普通的 Printer
fun?providePrinter()?=?NetworkPrinter()
复制代码
Dagger 基本上是同 Kotlin 兼容的,但是您仍然要注意,来确保代码不会出问题:?使用 @field: 来限定字段属性,内联方法体,当对集合进行注入时使用 @JvmSuppressWildcards 注解。
本次 Dagger 带来的优化不会带来额外的损耗,遵循这些最佳实践,诸如启用增量注释处理、禁用格式化设置以及使用静态 @Provides 方法等,可以缩短项目的构建时间。
评论