溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

在Kotlin中使用Dagger會(huì)遇到的陷阱和優(yōu)化方法是什么

發(fā)布時(shí)間:2021-10-25 15:31:51 來源:億速云 閱讀:173 作者:iii 欄目:web開發(fā)

這篇文章主要講解了“在Kotlin中使用Dagger會(huì)遇到的陷阱和優(yōu)化方法是什么”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“在Kotlin中使用Dagger會(huì)遇到的陷阱和優(yōu)化方法是什么”吧!

在Kotlin中使用Dagger會(huì)遇到的陷阱和優(yōu)化方法是什么

提高構(gòu)建效率

為了縮短構(gòu)建時(shí)間,Dagger 在 v2.18 版本中新增了 對(duì) gradle 增量注解處理 (gradle’s incremental  annotation processing) 的支持。在 Dagger v2.24  版本中這個(gè)功能是默認(rèn)啟用的。如果您使用的是較低版本,您需要添加以下幾行代碼來激活該功能。

另外,您可以配置 Dagger 讓它不要格式化生成的代碼。這一選項(xiàng)是在 Dagger v2.18 版本中添加的,并且是 v2.23 版本中的默認(rèn)行為  (不再生成格式化代碼)。如果您使用的是較低的版本,同樣可以添加下面的代碼來禁用格式化代碼以縮短構(gòu)建時(shí)間。

在 build.gradle 中添加以下編譯參數(shù)來提高 Dagger 在構(gòu)建時(shí)的性能:

allprojects {     afterEvaluate {         extensions.findByName('kapt')?.arguments {             arg("dagger.formatGeneratedSource", "disabled")             arg("dagger.gradle.incremental", "enabled")         }      } }

另外,如果您使用的是 Kotlin DSL 腳本文件,那么您需要在 build.gradle.kts 文件中包含以下內(nèi)容:

kapt {     arguments {         arg("dagger.formatGeneratedSource", "disabled")         arg("dagger.gradle.incremental", "enabled")     } }

使用 Qualifier 作為 field 的屬性

在 Kotlin 的某個(gè) property 上添加注解時(shí),不清楚最終 Java 是否能夠在該 property 的 field 或者 method  中獲取到該注解。在注解之前添加 field: 前綴能夠確保 qualifier 會(huì)作用到正確的地方 (查看 官方文檔 獲取更多詳情)。

將 qualifier 作用于一個(gè)已注入的 field 的正確方法如下:

@Inject @field:MinimumBalance lateinit var minimumBalance: BigDecimal

下面的做法是不對(duì)的:

@Inject @MinimumBalance lateinit var minimumBalance: BigDecimal  // @MinimumBalance 被忽略了

忘記添加 field: 如果在 Dagger 中存在一個(gè)不匹配該類型的實(shí)例,則可能會(huì)導(dǎo)致注入到錯(cuò)誤的對(duì)象中。

在 Dagger v2.25 版本中已經(jīng)修復(fù)該問題了,如果您使用的是該版本,之前這樣的寫法會(huì)出現(xiàn)問題,現(xiàn)在不會(huì)了。

@Inject @MinimumBalance lateinit var minimumBalance: BigDecimal  // 已修復(fù):@MinimumBalance 不再被忽略

使用靜態(tài)的 @Provides 方法來提高性能

如果使用的是靜態(tài)的 @Provides 方法,那么 Dagger 生成的代碼將具有更好的性能。要達(dá)成這一效果,使用 Kotlin 中的 object  而不是 class,并在方法前添加 @JvmStatic 注解。這是您應(yīng)該盡可能遵循的 最佳實(shí)踐 。

@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 來標(biāo)記 @Provides 函數(shù)了,Dagger 會(huì)正確地識(shí)別它。

泛型注入

Kotlin 使用通配符編譯泛型使 Kotlin API 和 Java 能一起使用。當(dāng)某個(gè)參數(shù)或者字段的類型為 泛型 時(shí),會(huì)在 Java  代碼中自動(dòng)生成。比如,Kotlin 的代碼 List 參數(shù)就會(huì)在 Java 中顯示為 List。

但這種特性會(huì)導(dǎo)致在 Dagger 中出現(xiàn)問題,因?yàn)樗谕愋褪峭耆?(也稱 invariant) 匹配的。使用 @JvmSuppressWildcards  將確保 Dagger 會(huì)看到?jīng)]有通配符的類型。

當(dāng)您使用 Dagger 的多重綁定特性時(shí),這是一個(gè)常常會(huì)遇到的問題,比如:

class MyVMFactory @Inject constructor(   private val vmMap: Map<String, @JvmSuppressWildcards  Provider<ViewModel>>  ) {      ...  }

在 Dagger v2.25 版本中,您將不再需要使用 @JvmSuppressWildcards 了,Dagger 會(huì)正確地識(shí)別它。

內(nèi)聯(lián)方法體

Dagger 通過檢查返回值類型來確定由 @Provides 方法配置的類型。在 Kotlin 函數(shù)中的返回類型是可選的,甚至 IDE  有時(shí)也會(huì)建議您重構(gòu)代碼使用內(nèi)聯(lián)方法體來隱藏返回值類型的聲明。

如果推斷的類型與您所期望的類型不一致,就會(huì)引起 bug 出現(xiàn)。我們來看一些例子:

如果要在 Dagger 中添加特定的類型,使用內(nèi)聯(lián)將是最好的選擇。我們來看看在 Kotlin 中實(shí)現(xiàn)同樣效果的另外一種方法:

@Provides  fun provideNetworkPrinter() = NetworkPrinter()  @Provides  fun provideNetworkPrinter(): NetworkPrinter = NetworkPrinter()  @Provides  fun provideNetworkPrinter(): NetworkPrinter {   return NetworkPrinter() }

如果您需要提供接口的實(shí)現(xiàn),則必須顯示指定返回類型。不這樣做的話會(huì)出問題:

@Provides // 配置 Printer fun providePrinter(): Printer = NetworkPrinter()  @Provides // 配置 NetworkPrinter,不是一個(gè)普通的 Printer fun providePrinter() = NetworkPrinter()

Dagger 基本上是同 Kotlin 兼容的,但是您仍然要注意,來確保代碼不會(huì)出問題: 使用 @field:  來限定字段屬性,內(nèi)聯(lián)方法體,當(dāng)對(duì)集合進(jìn)行注入時(shí)使用 @JvmSuppressWildcards 注解。

本次 Dagger 帶來的優(yōu)化不會(huì)帶來額外的損耗,遵循這些最佳實(shí)踐,諸如啟用增量注釋處理、禁用格式化設(shè)置以及使用靜態(tài) @Provides  方法等,可以縮短項(xiàng)目的構(gòu)建時(shí)間。

感謝各位的閱讀,以上就是“在Kotlin中使用Dagger會(huì)遇到的陷阱和優(yōu)化方法是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)在Kotlin中使用Dagger會(huì)遇到的陷阱和優(yōu)化方法是什么這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI