博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Android]在Dagger 2中使用RxJava来进行异步注入(翻译)
阅读量:7071 次
发布时间:2019-06-28

本文共 6181 字,大约阅读时间需要 20 分钟。

以下内容为原创,欢迎转载,转载请注明

来自天天博客:

在Dagger 2中使用RxJava来进行异步注入

原文:

几星期前我写了一篇关于在Dagger 2中使用Producers进行异步注入的。在后台线程中执行对象的初始化又一个很好的优势 - 它负责实时(可以保持界面流畅)绘制UI时不会在主线程中阻塞。

值得一提的是,缓慢的初始化过程并不是每个人都会觉得是个问题。但是如果你真的关心这个,所有外部库在构造以及在任何init()方法中进行磁盘/网络的操作会很常见。如果你不能确定这一点,我建议你尝试下 - 我的Android性能测量库。它会告诉你在app中需要花多少时间来显示特定的界面,还有(如果你使用了Dagger 2)在依赖图表中提供每个对象消耗了多少时间。

不幸的是Producers并不是为Android设计的,它有以下缺陷:

  • 依赖使用了Guava(会引起64k方法问题,增加build时间)
  • 并不是非常快的(注入机制会阻塞主线程几毫秒到几十毫秒的世界,这取决于设备)
  • (代码会有一点混乱)

虽然我们不能解决最后两个问题,但是第一个我们可以在Android Project中解决。

使用RxJava进行异步注入

幸运的是,有大量的Android开发者使用了RxJava(和)来在我们app中编写异步代码。让我们来尝试在Dagger 2中使用它来进行异步注入。

这是我们繁重的对象:

@Provides@SingletonHeavyExternalLibrary provideHeavyExternalLibrary() {    HeavyExternalLibrary heavyExternalLibrary = new HeavyExternalLibrary();    heavyExternalLibrary.init(); //This method takes about 500ms    return heavyExternalLibrary;}

现在让我们来创建一个额外的provide...()方法,它返回一个Observable<HeavyExternalLibrary>对象,它会异步调用以下代码:

@Singleton@ProvidesObservable
provideHeavyExternalLibraryObservable(final Lazy
heavyExternalLibraryLazy) { return Observable.create(new Observable.OnSubscribe
() { @Override public void call(Subscriber
subscriber) { subscriber.onNext(heavyExternalLibraryLazy.get()); } }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());}

让我们逐行来分析:

  • @Singleton - 记住这个很重要,Observable对象将会是一个单例,而不是HeavyExternalLibrary。Singleton也会阻止创建额外的Observable对象。
  • @Providers - 因为这个方法是@Module注解了的类的一部分。你还记得吗?
  • 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
heavyExternalLibraryObservable; //This will be injected asynchronously HeavyExternalLibrary heavyExternalLibrary; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(); //... heavyExternalLibraryObservable.subscribe(new SimpleObserver
() { @Override public void onNext(HeavyExternalLibrary heavyExternalLibrary) { //Our dependency will be available from this moment SplashActivity.this.heavyExternalLibrary = heavyExternalLibrary; } }); }}

异步新实例的注入

上面的代码展示了怎么去注入单例的对象。那如果我们想异步注入新的实例呢?

@ProvidesHeavyExternalLibrary provideHeavyExternalLibrary() {    HeavyExternalLibrary heavyExternalLibrary = new HeavyExternalLibrary();    heavyExternalLibrary.init(); //This method takes about 500ms    return heavyExternalLibrary;}

我们Observable<HeavyExternalLibrary> provider方法也会有一点改变。我们不能使用Lazy<HeavyExternalLibrary>因为它只会在第一次调用get()方法的时候(详见)才会创建新的实例。

这里是更新后的代码:

@Singleton@ProvidesObservable
provideHeavyExternalLibraryObservable(final Provider
heavyExternalLibraryProvider) { return Observable.create(new Observable.OnSubscribe
() { @Override public void call(Subscriber
subscriber) { subscriber.onNext(heavyExternalLibraryProvider.get()); } }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());}

我们的Observable<HeavyExternalLibrary>可以是一个单例,,但是每一次我们去调用它的subscribe()方法的时候,我们将会在onNext()方法中得到一个新的HeavyExternalLibrary实例:

heavyExternalLibraryObservable.subscribe(new SimpleObserver
() { @Override public void onNext(HeavyExternalLibrary heavyExternalLibrary) { //New instance of HeavyExternalLibrary }});

完全的异步注入

还有另一个方法是用RxJava在Dagger 2中进行异步注入。我们可以使用Observable简单封装整个注入过程。

我们注入的执行是这样的(代码摘自项目):

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()方法:

@Overrideprotected void setupActivityComponent() {    Observable.create(new Observable.OnSubscribe() {        @Override        public void call(Subscriber
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() { @Override public void onCompleted() { //Here is the moment when injection is done. analyticsManager.logScreenView(getClass().getName()); presenter.callAnyMethod(); } });}

正如注释,所有@Inject注解了的对象将被未来某一时刻注入。在返回注入过程是异步的并且不会对主线程有很大的影响。

当然创建Observable对象和额外subscribeOn()线程并不是完全免费的 - 它将会花费一点时间。这类似于Producers代码所产生的影响。

splash_metrics.png

感谢阅读!

作者

Head of Mobile Development @ 

[Android]使用Dagger 2依赖注入 - DI介绍(翻译):

[Android]使用Dagger 2依赖注入 - API(翻译):

[Android]使用Dagger 2依赖注入 - 自定义Scope(翻译):

[Android]使用Dagger 2依赖注入 - 图表创建的性能(翻译):

[Android]Dagger2Metrics - 测量DI图表初始化的性能(翻译):

[Android]使用Dagger 2进行依赖注入 - Producers(翻译):

[Android]在Dagger 

本文转自天天_byconan博客园博客,原文链接:

http://www.cnblogs.com/tiantianbyconan/p/6236646.html

,如需转载请自行联系原作者

你可能感兴趣的文章
How to: Create Instances of ASP.NET User Controls Programmatically
查看>>
关于 python中的 TKinterlistbox 控件加横竖滚动条
查看>>
【leetcode】258. Add Digits
查看>>
通过本地yum源安装软件报错[Errno 14] PYCURL ERROR 56 - "Failure when receiving data from the peer"...
查看>>
android常用调试工具fiddle、wireshark和android studio的配置
查看>>
Java实现几种常见排序方法
查看>>
NOIP2017 复盘
查看>>
jxa快速入门,Javascript已加入AppleScript全家桶
查看>>
洛谷P3622 动物园
查看>>
Angular Encapsulation - css选择器选不到非angular组件(插件)
查看>>
iOS开发之UIScrollView
查看>>
mysql 使用 insert ignore into和unique实现不插入重复数据功能
查看>>
c++操作符重载_12
查看>>
eclipse 安装反编译工具
查看>>
我的Java开发学习之旅------>Java多线程下载文件 实例
查看>>
WireShark简单使用以及TCP三次握手
查看>>
什么是@guid
查看>>
nodeType的12种类型
查看>>
步步为营 .NET 代码重构学习笔记 十三
查看>>
053:Field的常用参数详解:
查看>>