您好,登錄后才能下訂單哦!
這篇文章主要講解了“在Kotlin中使用Dagger會遇到的陷阱和優化方法是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“在Kotlin中使用Dagger會遇到的陷阱和優化方法是什么”吧!
提高構建效率
為了縮短構建時間,Dagger 在 v2.18 版本中新增了 對 gradle 增量注解處理 (gradle’s incremental annotation processing) 的支持。在 Dagger v2.24 版本中這個功能是默認啟用的。如果您使用的是較低版本,您需要添加以下幾行代碼來激活該功能。
另外,您可以配置 Dagger 讓它不要格式化生成的代碼。這一選項是在 Dagger v2.18 版本中添加的,并且是 v2.23 版本中的默認行為 (不再生成格式化代碼)。如果您使用的是較低的版本,同樣可以添加下面的代碼來禁用格式化代碼以縮短構建時間。
在 build.gradle 中添加以下編譯參數來提高 Dagger 在構建時的性能:
allprojects { afterEvaluate { extensions.findByName('kapt')?.arguments { arg("dagger.formatGeneratedSource", "disabled") arg("dagger.gradle.incremental", "enabled") } } }
另外,如果您使用的是 Kotlin DSL 腳本文件,那么您需要在 build.gradle.kts 文件中包含以下內容:
kapt { arguments { arg("dagger.formatGeneratedSource", "disabled") arg("dagger.gradle.incremental", "enabled") } }
使用 Qualifier 作為 field 的屬性
在 Kotlin 的某個 property 上添加注解時,不清楚最終 Java 是否能夠在該 property 的 field 或者 method 中獲取到該注解。在注解之前添加 field: 前綴能夠確保 qualifier 會作用到正確的地方 (查看 官方文檔 獲取更多詳情)。
將 qualifier 作用于一個已注入的 field 的正確方法如下:
@Inject @field:MinimumBalance lateinit var minimumBalance: BigDecimal
下面的做法是不對的:
@Inject @MinimumBalance lateinit var minimumBalance: BigDecimal // @MinimumBalance 被忽略了
忘記添加 field: 如果在 Dagger 中存在一個不匹配該類型的實例,則可能會導致注入到錯誤的對象中。
在 Dagger v2.25 版本中已經修復該問題了,如果您使用的是該版本,之前這樣的寫法會出現問題,現在不會了。
@Inject @MinimumBalance lateinit var minimumBalance: BigDecimal // 已修復:@MinimumBalance 不再被忽略
使用靜態的 @Provides 方法來提高性能
如果使用的是靜態的 @Provides 方法,那么 Dagger 生成的代碼將具有更好的性能。要達成這一效果,使用 Kotlin 中的 object 而不是 class,并在方法前添加 @JvmStatic 注解。這是您應該盡可能遵循的 最佳實踐 。
@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。
但這種特性會導致在 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 方法等,可以縮短項目的構建時間。
感謝各位的閱讀,以上就是“在Kotlin中使用Dagger會遇到的陷阱和優化方法是什么”的內容了,經過本文的學習后,相信大家對在Kotlin中使用Dagger會遇到的陷阱和優化方法是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。