比Dagger2好用一個(gè)量級(jí)-Hilt的使用和詳解

1 Hilt簡(jiǎn)介

Hilt 是 Android Jetpack中的依賴注入庫(kù)案糙,可減少項(xiàng)目代碼,用于模塊解耦靴庆。Hilt是在Dagger基礎(chǔ)上進(jìn)行二次封裝構(gòu)建的时捌,相對(duì)Dagger來說,代碼量更少炉抒,使用更簡(jiǎn)單端礼。不同的是,Dagger利用注解使用APT去生成輔助代碼佳镜,而Hilt是利用注解使用APT和ASM(字節(jié)碼插樁)去生成輔助代碼凡桥。

Hilt官網(wǎng):https://dagger.dev/hilt/

Google官網(wǎng)Hilt使用:https://developer.android.com/training/dependency-injection/hilt-android?hl=zh-cn

2 Hilt使用

2.1 引入依賴

根目錄build.gradle中添加hilt-android-gradle-plugin插件,最新版本可以在官網(wǎng)查看啊掏。

buildscript {
    dependencies {
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.41'
    }
}

在app目錄下build.gradle中添加以下依賴:

...
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'

android {
    ...
}

dependencies {
    implementation "com.google.dagger:hilt-android:2.28-alpha"
    kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
}

2.2 幾種常用注解

@Inject用來標(biāo)注需要依賴獲取的對(duì)象迟蜜。

@Module用來標(biāo)注提供依賴對(duì)象的類娜睛,也就是Module類,Module類中會(huì)有一個(gè)方法來提供依賴對(duì)象畦戒,在這個(gè)方法中可以對(duì)注入對(duì)象的有參構(gòu)造函數(shù)傳入?yún)?shù)或者進(jìn)行其他處理。

@Provides用來標(biāo)注Module類中的提供依賴對(duì)象的方法進(jìn)行標(biāo)注纵潦,該方法在需要提供依賴時(shí)被調(diào)用邀层,從而把預(yù)先提供好的對(duì)象當(dāng)做依賴給標(biāo)注了@Inject 的變量賦值晴裹。

@HiltAndroidApp 用來標(biāo)注Application,這個(gè)是必須到,如果沒有該注解经磅,程序會(huì)崩潰。該注解會(huì)觸發(fā) Hilt 的代碼生成操作阿迈,生成的代碼包括應(yīng)用的一個(gè)基類苗沧,該基類充當(dāng)應(yīng)用級(jí)依賴項(xiàng)容器炭晒。

@AndroidEntryPoint表示該類為接受依賴注入的對(duì)象,Hilt可以為帶有@AndroidEntryPoint注釋的Android類提供依賴項(xiàng)识樱。如果使用 @AndroidEntryPoint 為某個(gè) Android 類添加注釋震束,則還必須為依賴于該類的Android類添加注釋。例如割疾,如果為某個(gè)Fragment添加注釋宏榕,則還必須為使用該 Fragment 的所有 Activity 添加注釋。

@Binds用來綁定接口和實(shí)現(xiàn)類担扑,會(huì)告知 Hilt 在需要提供接口的實(shí)例時(shí)要使用哪種實(shí)現(xiàn)。

@InstallIn表示希望Hilt將該類注解到某處胚宦。比如BookModule類使用@InstallIn(ActivityComponent::class)枢劝,就表示BookModule中所有的額依賴項(xiàng)都可以在Activity中使用卜壕。

2.3 Hilt支持的類

Application(通過使用 @HiltAndroidApp)
Activity
Fragment
View
Service
BroadcastReceiver

2.4 Hilt為 Android 類生成的組件

對(duì)于可以從中執(zhí)行字段注入的每個(gè)Android類,都有一個(gè)關(guān)聯(lián)的 Hilt 組件鹤盒,可以 @InstallIn注釋中引用該組件侦副。每個(gè)Hilt組件負(fù)責(zé)將其綁定注入相應(yīng)的 Android 類。

Hilt組件 注入器面向的對(duì)象
ApplicationComponent Application
ActivityRetainedComponent ViewModel
ActivityComponent Activity
FragmentComponent Fragment
ViewComponent View
ViewWithFragmentComponent 帶有 @WithFragmentBindings 注釋的 View
ServiceComponent Service

2.5 使用@Provides注入實(shí)例

創(chuàng)建Book對(duì)象尺碰,示例中將使用hilt在Activity中獲取對(duì)象亲桥。

data class Book(val name: String)

創(chuàng)建BookModule题篷,用來提供Book對(duì)象玻驻。BookModule需要用@Module來標(biāo)注,表示這是一個(gè)提供依賴注入對(duì)象的類户辫。然后用@InstallIn(ActivityComponent::class)來標(biāo)注嗤锉,表示依賴注入將作用于Activity。

@Module
@InstallIn(ActivityComponent::class)
class BookModule {

    @Provides
    fun provideBook(): Book {
        return Book("三體")
    }
}

創(chuàng)建兩個(gè)Activity奥额,分別在兩個(gè)Activity中打印獲取到的Book對(duì)象的hashCode。

@AndroidEntryPoint//標(biāo)記這是一個(gè)注入點(diǎn)
class FirstActivity : AppCompatActivity() {

    private val TAG = "zhangmushui"

    //執(zhí)行對(duì)象注入
    @Inject
    lateinit var book: Book

    @Inject
    lateinit var book2: Book

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_first)

        findViewById<Button>(R.id.button).setOnClickListener {
            startActivity(
                Intent(
                    this,
                    SecondActivity::class.java
                )
            )
        }

        Log.d(TAG, "book hashCode: ${book.hashCode()}")
        Log.d(TAG, "book2 hashCode: ${book2.hashCode()}")
    }
}
@AndroidEntryPoint
class SecondActivity : AppCompatActivity() {

    private val TAG = "zhangmushui"

    @Inject
    lateinit var book: Book

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second)

        Log.d(TAG, "book3 hashCode: ${book.hashCode()}")

    }
}

運(yùn)行程序韩肝,查看log哀峻。

2022-04-21 18:26:16.730 22743-22743/cn.zhangmushui.hilt D/zhangmushui: book hashCode: 639594
2022-04-21 18:26:16.730 22743-22743/cn.zhangmushui.hilt D/zhangmushui: book2 hashCode: 639594
2022-04-21 18:26:21.580 22743-22743/cn.zhangmushui.hilt D/zhangmushui: book3 hashCode: 639594

可以看到剩蟀,3個(gè)Book對(duì)象額HashCode一致切威,Hilt默認(rèn)的依賴注入對(duì)象是單例的。

2.6 使用@Binds注入接口實(shí)例

創(chuàng)建一個(gè)接口BookService缰冤。

interface BookService {
    fun getBook()
}

實(shí)現(xiàn)這個(gè)接口烙无,打印一句話,注意需要用@Inject來標(biāo)注構(gòu)造方法。

class BookServiceImpl @Inject constructor() : BookService {

    override fun getBook() {
        Log.d("zhangmushui", "獲取到了一本書")
    }
}

創(chuàng)建Module類乾戏,用@Binds將接口和實(shí)現(xiàn)類關(guān)聯(lián)鼓择。

@Module
@InstallIn(ActivityComponent::class)
abstract class BookModule {

    @Binds
    abstract fun bindBookService(bookServiceImpl: BookServiceImpl): BookService
}

在Activity中,只需要通過@Inject去依賴注入接口類即可念搬。

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var bookService: BookService

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        bookService.getBook()
    }
}

可以看到摆出,無需手動(dòng)實(shí)例化接口實(shí)現(xiàn)類,即可調(diào)用接口爷恳。

3 Hilt原理解析

Hilt使用APT和ASM技術(shù)温亲,通過注解去生成輔助類。原理和Dagger2類似栈虚,說直白點(diǎn)就是各個(gè)類使用對(duì)應(yīng)的注解,就會(huì)生成對(duì)應(yīng)的輔助類曼验,然后把依賴注入對(duì)象實(shí)例化的工作交給這些輔助類去做头镊,所以就只通過注解就能達(dá)到獲取到對(duì)象的目的。

詳細(xì)分析可以參照模塊解耦神器-Dagger2的使用和詳解 - 簡(jiǎn)書 (jianshu.com)
颖杏,不同的地方是坛芽,Hilt會(huì)通過APT對(duì)依賴注入的作用類生成一個(gè)“Hilt_類名.java”類,然后該作用類會(huì)繼承這個(gè)生成類获讳,然后通過字節(jié)碼插樁活喊,在生成類中添加以下方法,從而實(shí)現(xiàn)依賴的注入帅矗。

protected void inject() {
    if (!injected) {
      injected = true;
      ((FirstActivity_GeneratedInjector) this.generatedComponent()).injectFirstActivity(UnsafeCasts.<FirstActivity>unsafeCast(this));
    }
  }

而使用Dagger2的時(shí)候浑此,這一部分代碼需要自己手動(dòng)在作用類中添加滞详。

本文完整源碼公眾號(hào)【木水Code】回復(fù)“Hilt”即可獲取。

關(guān)注木水小站 (zhangmushui.cn)和微信公眾號(hào)【木水Code】蒲犬,及時(shí)獲取更多最新文章稀火。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市沛慢,隨后出現(xiàn)的幾起案子达布,更是在濱河造成了極大的恐慌,老刑警劉巖躺苦,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匹厘,死亡現(xiàn)場(chǎng)離奇詭異脐区,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)牛隅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門媒佣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人欢嘿,你說我怎么就攤上這事也糊。” “怎么了?”我有些...
    開封第一講書人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵捕捂,是天一觀的道長(zhǎng)斗搞。 經(jīng)常有香客問我,道長(zhǎng)允悦,這世上最難降的妖魔是什么虑啤? 我笑而不...
    開封第一講書人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮全闷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘屏鳍。我一直安慰自己,他們只是感情好钓瞭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開白布山涡。 她就那樣靜靜地躺著搏讶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪系吩。 梳的紋絲不亂的頭發(fā)上妒蔚,一...
    開封第一講書人閱讀 51,698評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音科盛,去河邊找鬼菜皂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛恍飘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播母蛛,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼彩郊,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了秫逝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤剃根,失蹤者是張志新(化名)和其女友劉穎前方,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惠险,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡班巩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年抱慌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抑进。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡寺渗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出信殊,到底是詐尸還是另有隱情,我是刑警寧澤玲躯,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布鳄乏,位于F島的核電站,受9級(jí)特大地震影響汞窗,放射性物質(zhì)發(fā)生泄漏仲吏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一誓斥、第九天 我趴在偏房一處隱蔽的房頂上張望许帐。 院中可真熱鬧,春花似錦成畦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至跛梗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間核偿,已是汗流浹背嘁锯。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工家乘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人仁锯。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像野芒,于是被迫代替她去往敵國(guó)和親双炕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355