如下內容爲原創,歡迎轉載,轉載請註明
來自每天博客:http://www.cnblogs.com/tiantianbyconan/p/6236646.html
html
原文:http://frogermcs.github.io/async-injection-in-dagger-2-with-rxjavajava
幾星期前我寫了一篇關於在Dagger 2中使用Producers進行異步注入的文章。在後臺線程中執行對象的初始化又一個很好的優點 - 它負責實時(每秒60幀能夠保持界面流暢)繪製UI時不會在主線程中阻塞。git
值得一提的是,緩慢的初始化過程並非每一個人都會以爲是個問題。可是若是你真的關心這個,全部外部庫在構造以及在任何init()
方法中進行磁盤/網絡的操做會很常見。若是你不能肯定這一點,我建議你嘗試下AndroidDevMetrics - 個人Android性能測量庫。它會告訴你在app中須要花多少時間來顯示特定的界面,還有(若是你使用了Dagger 2)在依賴圖表中提供每一個對象消耗了多少時間。github
不幸的是Producers並非爲Android設計的,它有如下缺陷:api
雖然咱們不能解決最後兩個問題,可是第一個咱們能夠在Android Project中解決。網絡
幸運的是,有大量的Android開發者使用了RxJava(和RxAndroid)來在咱們app中編寫異步代碼。讓咱們來嘗試在Dagger 2中使用它來進行異步注入。app
這是咱們繁重的對象:異步
@Provides @Singleton HeavyExternalLibrary provideHeavyExternalLibrary() { HeavyExternalLibrary heavyExternalLibrary = new HeavyExternalLibrary(); heavyExternalLibrary.init(); //This method takes about 500ms return heavyExternalLibrary; }
如今讓咱們來建立一個額外的provide...()
方法,它返回一個Observable<HeavyExternalLibrary>
對象,它會異步調用如下代碼:async
@Singleton @Provides Observable<HeavyExternalLibrary> provideHeavyExternalLibraryObservable(final Lazy<HeavyExternalLibrary> heavyExternalLibraryLazy) { return Observable.create(new Observable.OnSubscribe<HeavyExternalLibrary>() { @Override public void call(Subscriber<? super HeavyExternalLibrary> subscriber) { subscriber.onNext(heavyExternalLibraryLazy.get()); } }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); }
讓咱們逐行來分析:ide
@Singleton
- 記住這個很重要,Observable
對象將會是一個單例,而不是HeavyExternalLibrary
。Singleton也會阻止建立額外的Observable對象。@Providers
- 由於這個方法是@Module
註解了的類的一部分。你還記得Dagger 2 API嗎?Lazy<HeavyExternalLibrary> heavyExternalLibraryLazy
對象阻止Dagger(不然,在調用provideHeavyExternalLibraryObservable()
方法調用的瞬間對象就會被建立)內部對HeavyExternalLibrary對象的初始化。Observable.create(...)
代碼 - 它將在每次這個Observable被訂閱時經過調用heavyExternalLibraryLazy.get()
返回heavyExternalLibrary
對象。.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
- 默認狀況下RxJava代碼會在Observable被建立的線程中執行。這就是爲何咱們要把執行移動到後臺線程(這裏的Schedulers.io()
),而後在主線程中(AndroidSchedulers.mainThread()
)觀察結果。咱們的Observable像圖表中其它對象同樣被注入,可是heavyExternalLibrary
對象自己將會延遲一點纔可用:
public class SplashActivity { @Inject Observable<HeavyExternalLibrary> heavyExternalLibraryObservable; //This will be injected asynchronously HeavyExternalLibrary heavyExternalLibrary; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(); //... heavyExternalLibraryObservable.subscribe(new SimpleObserver<HeavyExternalLibrary>() { @Override public void onNext(HeavyExternalLibrary heavyExternalLibrary) { //Our dependency will be available from this moment SplashActivity.this.heavyExternalLibrary = heavyExternalLibrary; } }); } }
上面的代碼展現了怎麼去注入單例的對象。那若是咱們想異步注入新的實例呢?
確認咱們的對象再也不使用了@Singleton註解:
@Provides HeavyExternalLibrary provideHeavyExternalLibrary() { HeavyExternalLibrary heavyExternalLibrary = new HeavyExternalLibrary(); heavyExternalLibrary.init(); //This method takes about 500ms return heavyExternalLibrary; }
咱們Observable<HeavyExternalLibrary>
provider方法也會有一點改變。咱們不能使用Lazy<HeavyExternalLibrary>
由於它只會在第一次調用get()
方法的時候(詳見Lazy文檔)纔會建立新的實例。
這裏是更新後的代碼:
@Singleton @Provides Observable<HeavyExternalLibrary> provideHeavyExternalLibraryObservable(final Provider<HeavyExternalLibrary> heavyExternalLibraryProvider) { return Observable.create(new Observable.OnSubscribe<HeavyExternalLibrary>() { @Override public void call(Subscriber<? super HeavyExternalLibrary> subscriber) { subscriber.onNext(heavyExternalLibraryProvider.get()); } }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); }
咱們的Observable<HeavyExternalLibrary>
能夠是一個單例,,可是每一次咱們去調用它的subscribe()方法的時候,咱們將會在onNext()方法中獲得一個新的HeavyExternalLibrary
實例:
heavyExternalLibraryObservable.subscribe(new SimpleObserver<HeavyExternalLibrary>() { @Override public void onNext(HeavyExternalLibrary heavyExternalLibrary) { //New instance of HeavyExternalLibrary } });
還有另外一個方法是用RxJava在Dagger 2中進行異步注入。咱們可使用Observable簡單封裝整個注入過程。
咱們注入的執行是這樣的(代碼摘自GithubClient項目):
public class SplashActivity extends BaseActivity { @Inject SplashActivityPresenter presenter; @Inject AnalyticsManager analyticsManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } //This method is called in super.onCreate() method @Override protected void setupActivityComponent() { final SplashActivityComponent splashActivityComponent = GithubClientApplication.get(SplashActivity.this) .getAppComponent() .plus(new SplashActivityModule(SplashActivity.this)); splashActivityComponent.inject(SplashActivity.this); } }
要讓它變成異步咱們只須要使用Observable封裝setupActivityComponent()
方法:
@Override protected void setupActivityComponent() { Observable.create(new Observable.OnSubscribe<Object>() { @Override public void call(Subscriber<? super Object> subscriber) { final SplashActivityComponent splashActivityComponent = GithubClientApplication.get(SplashActivity.this) .getAppComponent() .plus(new SplashActivityModule(SplashActivity.this)); splashActivityComponent.inject(SplashActivity.this); subscriber.onCompleted(); } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new SimpleObserver<Object>() { @Override public void onCompleted() { //Here is the moment when injection is done. analyticsManager.logScreenView(getClass().getName()); presenter.callAnyMethod(); } }); }
正如註釋,全部@Inject
註解了的對象將被將來某一時刻注入。在返回注入過程是異步的而且不會對主線程有很大的影響。
固然建立Observable
對象和額外subscribeOn()
線程並非徹底免費的 - 它將會花費一點時間。這相似於Producers代碼所產生的影響。
感謝閱讀!
Head of Mobile Development @ Azimo
[Android]使用Dagger 2依賴注入 - DI介紹(翻譯):
http://www.cnblogs.com/tiantianbyconan/p/5092083.html
[Android]使用Dagger 2依賴注入 - API(翻譯):
http://www.cnblogs.com/tiantianbyconan/p/5092525.html
[Android]使用Dagger 2依賴注入 - 自定義Scope(翻譯):
http://www.cnblogs.com/tiantianbyconan/p/5095426.html
[Android]使用Dagger 2依賴注入 - 圖表建立的性能(翻譯):
http://www.cnblogs.com/tiantianbyconan/p/5098943.html
[Android]Dagger2Metrics - 測量DI圖表初始化的性能(翻譯):
http://www.cnblogs.com/tiantianbyconan/p/5193437.html
[Android]使用Dagger 2進行依賴注入 - Producers(翻譯):
http://www.cnblogs.com/tiantianbyconan/p/6234811.html
[Android]在Dagger 2中使用RxJava來進行異步注入(翻譯):
http://www.cnblogs.com/tiantianbyconan/p/6236646.html
[Android]使用Dagger 2來構建UserScope(翻譯):
http://www.cnblogs.com/tiantianbyconan/p/6237731.html
[Android]在Dagger 2中Activities和Subcomponents的多綁定(翻譯):
http://www.cnblogs.com/tiantianbyconan/p/6266442.html