如下内容为原创,欢迎转载,转载请注明
来自每天博客: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