一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 在 Kotlin 中使用 Dagger 會遇到的陷阱和優(yōu)化方法

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

2020-11-04 00:14掘金Android開發(fā)者 Java教程

本文的寫作靈感來自 Dagger issue 中的一些建議,這些建議直接代表了在 Kotlin 中使用 Dagger 的最佳實踐和一些痛點。在此要感謝所有的 issue 貢獻者。

Dagger 在 Android 開發(fā)中相當流行,它是一個提供完全靜態(tài)和在編譯時生成代碼的依賴注入框架,它解決了很多基于反射而實現(xiàn)的方案中所遇到的開發(fā)和性能問題。

為了讓您更好地了解 Dagger 的工作原理,我們于 2019 年發(fā)布了一個 新的教程。本文將重點介紹如何 在 Kotlin 中使用 Dagger ,包括優(yōu)化構建時間的 最佳實踐 以及一些可能會遇到的問題。

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

Dagger 是通過 Java 的注解模型實現(xiàn)的,而 Kotlin 中注解的編寫方式同 Java 的并不是一一對應的,這篇文章會重點介紹它們之間的不同之處,并且會介紹怎樣輕松地將 Dagger 同 Kotlin 結合起來使用。

本文的寫作靈感來自 Dagger issue 中的一些建議,這些建議直接代表了在 Kotlin 中使用 Dagger 的最佳實踐和一些痛點。在此要感謝所有的 issue 貢獻者。

提高構建效率

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

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

在 build.gradle 中添加以下編譯參數(shù)來提高 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 版本中已經修復該問題了,如果您使用的是該版本,之前這樣的寫法會出現(xiàn)問題,現(xiàn)在不會了。

@Inject @MinimumBalance lateinit var minimumBalance: BigDecimal  

// 已修復:@MinimumBalance 不再被忽略 

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

如果使用的是靜態(tài)的 @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 函數(shù)了,Dagger 會正確地識別它。

泛型注入

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

但這種特性會導致在 Dagger 中出現(xiàn)問題,因為它期望類型是完全 (也稱 invariant) 匹配的。使用 @JvmSuppressWildcards 將確保 Dagger 會看到沒有通配符的類型。

當您使用 Dagger 的多重綁定特性時,這是一個常常會遇到的問題,比如:

class MyVMFactory @Inject constructor( 

  private val vmMap: Map<String, @JvmSuppressWildcards  

Provider<ViewModel>> 

 

) {  

    ...  

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

內聯(lián)方法體

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

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

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

@Provides  

fun provideNetworkPrinter() = NetworkPrinter() 

 

@Provides  

fun provideNetworkPrinter(): NetworkPrinter = NetworkPrinter() 

 

@Provides  

fun provideNetworkPrinter(): NetworkPrinter { 

  return NetworkPrinter() 

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

@Provides 

// 配置 Printer 

fun providePrinter(): Printer = NetworkPrinter() 

 

@Provides 

// 配置 NetworkPrinter,不是一個普通的 Printer 

fun providePrinter() = NetworkPrinter() 

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

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

原文地址:https://juejin.im/post/6890148357608570888

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 男人和女人日 | 亚洲精品福利你懂 | 国产成人一区二区三区小说 | 日本国产高清色www视频在线 | 男人躁女人p | 韩国三级年轻小的胰子完整 | 啪啪导航 | 国产欧美成人不卡视频 | 2021国产麻豆剧传媒剧情 | 护士被多人调教到失禁h | 色多多视频在线 | 国产91素人搭讪系列天堂 | 手机看片福利 | 小黄文污到你湿 | 欧美高清乌克兰精品另类 | 欧美日韩亚洲一区二区三区在线观看 | 成人免费视屏 | 青青草国产精品免费 | 亚洲国产高清一区二区三区 | 奇米影视久久 | 九九99九九精彩 | 女被男啪到哭 | 成年人福利 | 亚洲欧美成人综合 | 97国产精品久久碰碰牛牛 | 国产成人免费视频 | 邪恶肉肉全彩色无遮琉璃神社 | 91免费播放人人爽人人快乐 | 40分钟在线观看免费 | 好姑娘在线观看完整版免费 | www.四虎在线观看 | 九九热在线视频观看这里只有精品 | 国产精品久久国产精品99盘 | 国产欧美日韩不卡一区二区三区 | 亚裔aⅴ艳星katsuni | 欧美综合在线 | 免费一级毛片在线播放 | 18未年禁止免费观看 | 99热这里只有精品久久免费 | 成品人视频w免费观看w | 国产婷婷综合丁香亚洲欧洲 |