天天看點

[Android]使用Dagger 2進行依賴注入 - Producers(翻譯)使用Dagger 2進行依賴注入 - Producers

本文是在Android中使用Dagger 2架構進行依賴注入的系列文章中的一部分。今天我們将探索下Dagger Producers - 使用Java實作異步依賴注入的Dagger2的一個擴充。

我們都知道Dagger 2是一個優化得很好的依賴注入架構。但是即使有這些全部的微優化,仍然在依賴注入的時候存在可能的性能問題 - “笨重”的第三方庫和/或我們那些主線程阻塞的代碼。

依賴注入是在盡可能短的時間内在正确的地方傳遞所請求的依賴的過程 - 這些都是Dagger 2做得很好的。但是DI也會去建立各種依賴。如果我們需要花費幾百毫秒建立它們,那麼以納秒級的時間去提供依賴還有什麼意義呢?

當我們的app建立了一系列繁重的單例并立即由Dagger2提供服務之後也許可能沒有這麼重要。但是在我們建立它們的時候仍然需要一個時間成本 - 大多數情況下決定了app啟動的時間。

在很短的時間内,讓我們想象這麼一個場景 - 你的app有一個初始化的界面(SplashScreen),需要在app啟動後立即做一些需要的事情:

初始化所有tracking libs(Goole Analytics, Crashlytics)然後發送第一份資料給它們。

建立用于API和/或資料庫通信的整個棧。

我們試圖的互動邏輯(MVP中的Presenters,MVVM中的ViewModels等等)。

即使我們的代碼是優化地非常好的,但是仍然有可能有些額外的庫需要幾十或者幾百毫秒的時間來初始化。在我們啟動界面之前将展示必須初始化和傳遞的所有請求的依賴(和它們的依賴)。這意味着啟動時間将會是它們每一個初始化時間的總和。

[Android]使用Dagger 2進行依賴注入 - Producers(翻譯)使用Dagger 2進行依賴注入 - Producers

使用者将會在600ms(+額外的系統work)内看到SplashActivity - 所有初始化時間的總和。

Dagger 2 有一個名為 Producers 的擴充,或多或少能為我們解決這些問題。

思路很簡單 - 整個初始化流程可以在一個或多個背景線程中被執行,然後延後再傳遞給app的主線程。

類似于<code>@Module</code>,這個被用來标記用于傳遞依賴的類。多虧于它,Dagger将會知道去哪裡找到被請求的依賴。

類似于<code>@Provide</code>,這個注解用來标記帶有<code>@ProducerModule</code>注解的類中的傳回依賴的方法。<code>@Produces</code>注解的方法可以傳回<code>ListenableFuture&lt;T&gt;</code>或者自身的對象(也會在所給的背景線程中進行初始化)。

類似于<code>@Component</code>,它負責依賴的傳遞。它是我們代碼與<code>@ProducerModule</code>之間的橋梁。唯一跟<code>@Component</code>的不同之處是我們不能決定依賴的scope。這意味着提供給 component 的每一個 Produces 方法 在 每個component 執行個體中最多隻會被調用一次,不管它作為一個 依賴 用于多少次綁定。

也就是說,每一個服務于<code>@ProductionComponent</code>的對象都是一個單例(隻要我們從這個特殊的component中擷取)。

在我們開始實踐前,有一些值得提醒的事情。Producers相比Dagger 2本身有一點更複雜。它看起來手機端app不是他們它們主要使用的目标,而且知道這些事情很重要:

Producers使用了Guava庫,并且建立在ListenableFuture類之上。這意味着你不得不處理15k的額外方法在你的app中。這可能導緻你不得不使用Proguard來處理并且需要一個更長的編譯時間。

就如你将看到的,建立<code>ListenableFutures</code>并不是沒有成本的。是以如果你指望Producers會幫你從10ms優化到0ms那你可能就錯了。但是如果規模更大(100ms --&gt; 10ms),你就能有所發現。

現在無法使用<code>@Inject</code>注解,是以你必須要手動處理ProductionComponents。它會使得你的标準整潔的代碼變得混亂。

[Android]使用Dagger 2進行依賴注入 - Producers(翻譯)使用Dagger 2進行依賴注入 - Producers

我們的計劃是處理UserManager讓它的所有的依賴來自Producers。

我們将給一個Dagger v2.1的嘗試(但是目前2.0版本的Producers也是可用的)。

讓我們在項目中加入一個Dagger新的版本:

app/build.gradle:

如你所見,Producers 作為一個新的依賴,在dagger 2庫的下面。還有值得一說的是Dagger v2.1終于不需要<code>org.glassfish:javax.annotation:10.0-b28</code>的依賴了。

GithubApiProducerModule.java

看起來很像?沒錯,我們隻是修改了:

<code>@Module</code> 改為 <code>@ProducerModule</code>

<code>@Provides @Singleton</code> 改為 <code>@Produces</code>。你還記得嗎?在Producers中我們預設就有一個單例

<code>UserModule.Factory</code> 依賴隻是因為app的邏輯原因而添加。

現在讓我們建立<code>@ProductionComponent</code>,它将會為<code>UserManager</code>執行個體提供服務:

ProductionComponent的建構也是與标準的Component非常相似:

額外附加的參數是<code>Executor</code>執行個體,它告訴ProductionComponent依賴應該在哪裡(哪個線程)被建立。在我們的例子中我們使用了一個single-thread executor,但是當然增加并行級别并使用多線程執行不是一個問題。

這裡重要的是,對象初始化是在你第一次調用<code>appProductionComponent.userManager()</code>的時候開始的。在這之後<code>UserManager</code>對象将會被緩存。這表示每一個綁定都擁有跟component執行個體相同的生命周期。

以上幾乎就是所有了。當然你應該知道在<code>Future.onSuccess()</code>方法被調用之前userManager執行個體會時<code>null</code>。

在最後讓我們來看下現在注入的性能是怎麼樣的:

[Android]使用Dagger 2進行依賴注入 - Producers(翻譯)使用Dagger 2進行依賴注入 - Producers

是的,沒錯 - 這時平均值大約是15ms。它小于同步注入(平均. 25ms)但是并不如你期望的那樣少。這時因為Producers并不像Dagger本身那樣輕量。

是以現在取決于你了 - 是否值得使用Guava, Proguard和代碼複雜度來做這種優化。

請記住,如果你覺得Producers并不是最适合你的app的,你可以在你的app中嘗試使用RxJava或者其他異步代碼來包裝你的注入。

感謝閱讀!

<a href="http://about.me/froger_mcs">Miroslaw Stanek</a>

[Android]使用Dagger 2依賴注入 - DI介紹(翻譯): <a href="http://www.cnblogs.com/tiantianbyconan/p/5092083.html">http://www.cnblogs.com/tiantianbyconan/p/5092083.html</a>
[Android]使用Dagger 2依賴注入 - API(翻譯): <a href="http://www.cnblogs.com/tiantianbyconan/p/5092525.html">http://www.cnblogs.com/tiantianbyconan/p/5092525.html</a>
[Android]使用Dagger 2依賴注入 - 自定義Scope(翻譯): <a href="http://www.cnblogs.com/tiantianbyconan/p/5095426.html">http://www.cnblogs.com/tiantianbyconan/p/5095426.html</a>
[Android]使用Dagger 2依賴注入 - 圖表建立的性能(翻譯): <a href="http://www.cnblogs.com/tiantianbyconan/p/5098943.html">http://www.cnblogs.com/tiantianbyconan/p/5098943.html</a>
[Android]Dagger2Metrics - 測量DI圖表初始化的性能(翻譯): <a href="http://www.cnblogs.com/tiantianbyconan/p/5193437.html">http://www.cnblogs.com/tiantianbyconan/p/5193437.html</a>
[Android]使用Dagger 2進行依賴注入 - Producers(翻譯): <a href="http://www.cnblogs.com/tiantianbyconan/p/6234811.html">http://www.cnblogs.com/tiantianbyconan/p/6234811.html</a>
<b>本文轉自天天_byconan部落格園部落格,原文連結:</b> <b>http://www.cnblogs.com/tiantianbyconan/p/6234811.html</b> <b>,如需轉載請自行聯系原作者</b>

繼續閱讀