当前位置: 首页 > 科技观察

Kotlin中使用Dagger遇到的坑和优化方法

时间:2023-03-23 01:29:57 科技观察

Dagger在Android开发中相当流行。它是一个依赖注入框架,提供完全静态和编译时生成的代码。场景中遇到的开发和性能问题。为了让您更好地了解Dagger的工作原理,我们在2019年发布了一个新教程。本文将重点介绍如何在Kotlin中使用Dagger,包括优化构建时间的最佳实践和一些可能的陷阱。Dagger是通过Java的注解模型实现的,Kotlin的注解写法和Java的不是一一对应的。本文将重点介绍它们之间的区别以及如何轻松地将Dagger与Java集成。科特林结合。这篇文章的写作灵感来自于Daggerissue中的一些建议,这些建议直接代表了在Kotlin中使用Dagger的最佳实践和一些痛点。感谢所有问题贡献者。提高构建效率为了缩短构建时间,Dagger在v2.18中增加了对gradle增量注解处理的支持。此功能在Daggerv2.24中默认启用。如果您使用的是早期版本,则需要添加以下代码行来激活该功能。此外,您可以将Dagger配置为不格式化生成的代码。该选项是在Daggerv2.18中添加的,是v2.23中的默认行为(不再生成格式化代码)。如果您使用的是较低版本,您还可以添加以下代码以禁用格式化代码以缩短构建时间。在build.gradle中添加以下编译参数以提高Dagger在构建时的性能:dagger.gradle.incremental","enabled")}}}此外,如果您使用的是KotlinDSL脚本文件,则需要在build.gradle.kts文件中包含以下内容:kapt{arguments{arg("dagger.formatGeneratedSource","disabled")arg("dagger.gradle.incremental","enabled")}}在Kotlin中使用Qualifier作为字段的属性为属性添加注解时,不清楚Java是否可以在该属性的字段中使用或者获取方法中的注解。在注释前添加field:prefix将确保将限定符应用到正确的位置(有关更多详细信息,请参阅官方文档)。将限定符应用于注入字段的正确方法如下:@Inject@field:MinimumBalancelateinitvarminimumBalance:BigDecimal以下方法是错误的:@Inject@MinimumBalancelateinitvarminimumBalance:BigDecimal//@MinimumBalance被忽略并忘记添加字段:如果在Dagger中存在与类型不匹配的实例可能会导致注入到错误的对象中。这个问题在Daggerv2.25版本中已经修复。如果你用的是这个版本,以前这种写法会有问题,现在不会了。@Inject@MinimumBalancelateinitvarminimumBalance:BigDecimal//修正:不再忽略@MinimumBalance使用静态@Provides方法提高性能如果使用静态@Provides方法,Dagger生成的代码将具有更好的性能。要达到这个效果,使用Kotlin对象代替类,并在方法前添加@JvmStatic注解。这是您应该尽可能遵循的最佳实践。@ModuleobjectNetworkModule{@JvmStatic@ProvidesfunprovideOkHttpClient():OkHttpClient{returnOkHttpClient.Builder().build()}}如果需要使用抽象方法,需要在伴生对象上加上@JvmStatic,并加上@Module注解。@ModuleabstractclassNetworkModule{@BindsabstractfunprovideService(retrofitService:RetrofitService):Service@Modulecompanionobject{@JvmStatic@ProvidesfunprovideOkHttpClient():OkHttpClient{returnreturnOkHttpClient.Builder().build()}}}或者你可以提取模块代码对象包在抽像中模块:@Module(includes=[OkHttpClientModule::java])abstractclassNetworkModule{@BindsabstractfunprovideService(retrofitService:RetrofitService):Service}@ModuleobjectOkHttpClientModule{@JvmStatic@ProvidesfunprovideOkHttpClient():OkHttpClient{returnOkHttp.Client()}Dagger()}v2.25版本,不再需要使用@JvmStatic来标记@Provides函数,Dagger会正确识别。泛型注入Kotlin使用通配符编译泛型,使KotlinAPI能够与Java一起使用。当参数或字段的类型为泛型时,会在Java代码中自动生成。例如,Kotlin中的代码List参数将在Java中显示为List。但是这个特性在Dagger中会导致问题,因为它期望类型是精确的(又名不变的)匹配。使用@JvmSuppressWildcards将确保Dagger将看到没有通配符的类型。这是你使用Dagger的多绑定特性时的一个常见问题,比如:classMyVMFactory@Injectconstructor(privatevalvmMap:Map>){...}在Daggerv2.25版本中,你将不再需要使用@JvmSuppressWildcards,Dagger会正确识别它。内联方法体Dagger检查返回类型以确定@Provides方法配置的类型。返回类型在Kotlin函数中是可选的,甚至IDE有时也会建议您重构代码以使用内联方法体来隐藏返回类型声明。如果推断的类型与您的预期不匹配,这可能会导致错误。让我们看一些例子:如果你想在Dagger中添加特定的类型,使用内联将是最好的选择。让我们看看在Kotlin中实现相同效果的另一种方法:@ProvidesfunprovideNetworkPrinter()=NetworkPrinter()接口实现必须显式指定返回类型。如果不这样做,就会出现问题:@Provides//ConfigurePrinterfunprovidePrinter():Printer=NetworkPrinter()@Provides//ConfigureNetworkPrinter,不是普通的PrinterfunprovidePrinter()=NetworkPrinter()Dagger基本兼容Kotlin,但您仍然需要注意确保代码不会中断:使用@field:限定字段属性、内联方法体,并在注入集合时使用@JvmSuppressWildcards注释。这次Dagger带来的优化不会带来额外的损失。遵循这些最佳实践,例如启用增量注释处理、禁用格式设置和使用静态@Provides方法等,可以缩短项目的构建时间。