要看視頻的能夠直接去 嗶哩嗶哩 觀看。不方便看視頻的,下面文章搞起。markdown
說到依賴注入,作 Android 的人都會想到一個庫:Dagger;說到 Dagger,你們的反應廣泛是一套三連:牛逼、高端、我纔不用。
又牛逼又高端,爲何不用?由於太難了。是吧?又難學又難用。大多數的人在學習 Dagger 的路上就被直接勸退了,剩下的這一小撮人最終排除萬難,學會而且用上了 Dagger,但多半都是用着用着就掉進了本身親手用 Dagger 搭建的迷宮裏,怎麼也繞不清楚,並且越陷越深,就這麼成年累月地被它折磨。
有人可能會說:難用就別用唄?拆出來啊。
拆?哼哼。你對 Dagger 一無所知。
而就在上個月,Android 團隊又在 Jetpack 裏面又增長了一個新的依賴注入庫:Hilt。這個 Hilt 是專門針對於 Android 平臺的依賴注入庫,它是基於 Dagger 的。
框架
啊?基於……Dagger?此次究竟是真正的神器到來,仍是又一個大坑?ide
Dagger 的名字取自有向無環圖 DAG (directed acyclic graph):
由於程序裏的依賴關係拼接起來就是一個或者多個有向無環圖:
DAG-er,Dagger,取了個諧音,Dagger 是匕首的意思。而此次的 Hilt 是刀柄的意思,匕首很難用是吧?來,給你個柄。
說得很好聽,到底有沒有那麼好用啊?這是個複雜的問題,且聽我慢慢道來~
函數
Hilt 好很差用,咱們先來看看它是個什麼。它是個用註解來進行配置的依賴注入庫。註解是它的寫法,首先它是個依賴注入庫,對吧?什麼是依賴注入?一個類裏有兩個變量,這兩個變量就是它的依賴:
要初始化一個依賴,有兩種方法:第一,你這個類本身初始化:
第二,讓外部幫你初始化。
其中這第二種,讓外部幫你初始化你的依賴,就叫依賴注入。關鍵在於初始化是誰作的,至於最後一步是你把結果拿過來,仍是說你連拿都不用拿,最後一步的賦值工做也讓外部來幫你作了,這都不重要,只要初始化工做是外部作的,就都叫依賴注入。
因此 Factory 的使用是依賴注入嗎?
是的。
Builder?
也是。
帶參數的構造函數?
也是!
這些都屬於由外部來提供依賴的初始化,因此都是依賴注入,並非非要像 Dagger 那樣使用註解的像魔法同樣的才叫依賴注入。也就是說,其實咱們每一個人都已經在使用依賴注入了。雖然不少人在面對 Dagger 的時候會問「依賴注入到底有什麼用」,但其實 Dagger 並非提供了依賴注入的能力,而是爲依賴注入提供了一種更簡單的方式。依賴注入原本就是有用的,這個問題不想明白,不論是 Dagger 仍是如今的 Hilt,你都用很差。
Dagger 讓咱們能夠用註解的方式來配置依賴關係,讓依賴注入變得更方便。不過因爲功能複雜,致使它的上手很是困難;再加上剛纔我說的,不少人對於依賴注入的做用以及 Dagger 的定位都沒搞清楚,這兩個緣由加起來,就致使不少人還沒學會 Dagger 就把它棄了,讓 Dagger 成爲 Android 史上最受冷落的優質庫。這樣的結果不管是對 Dagger 仍是對咱們,都是很惋惜的。
而 Hilt 的出現,就直接解決了 Dagger 太複雜的這個問題。
工具
Hilt 是 Google 專門針對 Android 平臺作的一個依賴注入庫。它不是從裏到外全新開發的,而是基於 Dagger 作的,它的下層仍是 Dagger。
爲何不直接去優化改進 Dagger,而要基於它作一個新庫呢?由於 Hilt 作的事其實也並非對 Dagger 進行優化,而是場景化:針對 Android 開發制定了一系列的規則,經過這些規則大大簡化了這套工具的使用。例如在 Dagger 裏,你要對某個類的依賴進行注入,你須要手動獲取依賴圖和執行注入依賴操做:
而在 Hilt 裏,注入會自動完成:
由於 Hilt 會自動找到 Android 的系統組件裏面那些最佳的初始化位置——好比 Activity 的 onCreate()
——而後在這些位置注入依賴。因此,爲何不是去優化 Dagger,而是作了個新庫?由於 Hilt 自己並非一種優化,而是場景化,或者說,它是一種針對場景的優化。總之,它是不通用的,只能給 Android 用,因此不能放在 Dagger 裏。
有點明白了吧?
那它具體怎麼用呢?大概是這樣的:
咱們程序裏有些對象是全局共享的,好比線程池,或者 Retrofit 對象,這種東西咱們一般會把它放在 Application 對象裏,或者作成單例的:
而若是用 Hilt,你也能夠把它作成自動注入的依賴:
還有些對象是局部共享的,好比某個 Activity 會把一些顯示用的數據共享給它內部的一些 View 和 Fragment。這一類狀況咱們的作法一般是獲取外部 Activity 對象而後強轉,再去拿它內部的對象:
而若是用 Hilt,你能夠把這個對象直接聲明出來,讓它自動注入:
這不僅是一個「美觀」的差異,依賴注入可讓你的程序更加靈活,好比若是你的 View 能夠在多個不一樣的 Activity 裏顯示,那你在 View 裏面要怎麼強轉?你要轉成誰?
很麻煩,是吧?而若是用依賴注入,這些就都是自動的。
除了共享的對象,不共享的也能夠用依賴注入的方式來進行初始化,由於依賴注入的做用除了對共享對象提供一致性支持,也可讓咱們在建立任何對象的時候省一些思考和力氣:
oop
@Inject newUser: User 複製代碼
總之,若是一個組件可能會被被共享,或者不會被共享但可能會在多處使用,你均可以使用 Hilt 來把它配置成依賴注入的加載方式。
加載的方式能夠選擇直接調用構造函數:
或者指定子類或實現類:
或者乾脆給出具體的代碼:
加載的做用域能夠選擇默認的每次都初始化,也能夠設置成全局單例的:
也能夠設置成針對任何 Activity、Fragment、View 或者 ViewModel 的局部共享:
簡單又強大,好用又靈活。具體的寫法你能夠去看文檔,或者過段時間我會有一次公開課,到時候也會提早通知你們。
到這裏有的人可能會分個叉可能會想:誒 ButterKnife 或者如今 Jetpack 推出的 ViewBinding 它們提供的功能,Hilt 提供了嗎?由於若是提供了,我在用了 Hilt 以後,不就能夠把 ButterKnife 和 ViewBinding 扔掉了?
很差意思,Hilt 不提供它們的功能。Hilt 和 Dagger 雖然用法和 ButterKnife 很像,都是給變量加註解,而後變量會自動賦值,但它們的功能定位是不同的:Hilt 和 Dagger 是作依賴注入的,而 ButterKnife 和 ViewBinding 是作視圖綁定的。
這可不是個文字遊戲,依賴注入和視圖綁定是有本質區別的:依賴注入是由外部對對象進行初始化,也就是所謂的控制翻轉;而視圖綁定是讓變量去指向一個已經有了的 View,它的依賴依然是由依賴持有者本身決定的,這是一個本質的區別。
更多它們的區別我就不細講了,想了解的話,給你推薦個東西:在這個世界上有一我的叫扔物線,他出了一套 Android 高級進階系列化課程,這套課程涵蓋了中高級 Android 工程師進階提高須要的方方面面,其中依賴注入和視圖綁定的區別——只是冰山一角。而你只須要作一件事:報名,買它。學完這套課,你會收穫技術和薪資的雙重提高——固然你得好好學啊,個人課含金量比較高,刷起來可能有點慢,可是隻要認真刷完,你就再也不是你了。
快掃掃碼呀!(恰本身家的飯,真香)
學習
這麼看來,Hilt 仍是很好用的,是吧?那有些人就又有問題了:哎,Hilt 這麼好用,那Dagger 真的難用嗎?到底難用在哪了?
其實說白了,Dagger 的難用主要在於這個框架太強大和靈活了,致使你要遵照不少約定才能正確使用它。好比在 Hilt 裏,一個註解就能讓 Activity 內部的依賴自動被注入,而 Dagger 須要手動注入;再好比在 Hilt 裏若是你想讓一個對象只在 Activity 內部被共享而不是全局共享,也就是一個註解能解決的問題,而在 Dagger 裏面你須要先去建立一個自定義的註解。這些難嗎?每一個都不難的,對吧?但把它們放在一塊兒,讓你靈活搭配使用,就有點難了。
另外,Dagger 被你們廣泛認爲難的另外一個緣由剛纔我也說過了:不少人連依賴注入都不太懂的。因此我再說一遍:若是一個組件可能被共享,或者可能在多處被使用,你可使用依賴注入來初始化它。而後,在須要依賴注入的場景裏,使用 Dagger 能讓你的依賴注入寫起來更簡單。最後,Hilt 進一步簡化了這個事情。先知道它是什麼,再去用它。
其實我在個人知識星球裏也分享了依賴注入的使用原則(球友們沒看的快去看看):
你若是是一個追求技術的 Android 工程師,很是推薦加入個人星球,我在這裏會對於各類好的、新的、難的技術給出技術分享和個人我的看法,微軟中國的 Android 工程師 Drakeet 許曉鋒也在這裏和我一塊兒分享知識和經驗:
以及,你在個人視頻和公開課裏看到的東西也能夠在星球討論和問我。
優化
啊我收!
因此今天表面上是在介紹 Hilt,實際上是對於 Hilt 以及它背後的依賴注入機制進行一個總體的講解,但願對你能夠有幫助。你們學知識和技術的時候,必定不要只關注表面,要透過表面看到裏面的本質,掌握最核心的東西。
那麼回到這期的標題——《從 Dagger 到 Hilt,谷歌爲什麼執着於讓咱們用依賴注入》,爲何?其實谷歌並無非要讓咱們使用依賴注入,而是咱們原本就須要使用依賴注入,谷歌只是想提供一種更方便的方式讓咱們去使用依賴注入而已。Dagger 很強大,但太難學從而致使太難用;而 Hilt 完全掃除了這個障礙,那……
要不咱給它個機會?ui
本文使用 mdnice 排版spa