一、问题引入
此前对rxjava的诸多用法小小的进行过总结,rxjava的使用给代码设计带来了很多惊奇和方便。但是在了解到PublishSubject之后再次被rxjava的简便给折服了。在介绍PublishSubject之前,先容我给出这样一个命题,在Android的开发中,我们经常会在Service中处理批量下载的任务,然后将下载的进度显示在Activity中。如果需要完成Service中数据的更新到Activity数据的显示,可行的方案有哪些。
目前能够列举到的方案有如下:
1. DataBinding
2. 广播
3. EventBus
4. Rxjava的PublishSubject
这些方案中DataBinding,网上关于它的介绍不俗,但是我看实现中用起来还是有点麻烦,或许是我没有深入的了解和使用,它不是本文要介绍的重点。广播在使用中需要编写注册,解除注册的代码以及相关的BroadcastReceiver代码,代码量感觉小小的有点大。EventBus比广播要好一点点,但是同样需要注册EventBus和取消注册EventBus,只是可以通过注解来指定完成事件响应的函数。Rxjava的PublishSubject在设计中省去了注册和取消注册的逻辑,比广播和EventBus更高一筹。
二、Rxjava的PublishSubject的使用
以命题中介绍的Service进行批量下载,在Service中更新数据和Activity中显示数据为例来介绍Rxjava的PublishSubject的使用。
/**
*Service部分的代码逻辑
**/
import rx.Observable;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
import rx.subjects.PublishSubject;
public class DownLoadService extends Service {
...
private static final PublishSubject<DownloadInfo> EVENT_PUBLISH_SUBJECT = PublishSubject.create();//构造一个PublishSubject
/**
*提供对外的PublishSubject
**/
public static Observable<DownloadInfo> getStatusObservable() {
return EVENT_PUBLISH_SUBJECT.onBackpressureLatest();//此处采用Rxjava背压防止事件发生过快
}
/**
*对外发布下载更新的数据
**/
private void updateDownloadStatus(DownloadInfo downloadInfo) {
...
EVENT_PUBLISH_SUBJECT.onNext(chapterInfo);
...
}
Activity中的代码逻辑如下
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
import rx.subjects.PublishSubject;
public class DownloadActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
...
receiveCacheProgress();
...
}
/**
*从service中获取下载更新的数据
**/
private void receiveCacheProgress() {
DownloadService.getStatusObservable().compose(this.<DownloadInfo>avoidStateLoss()) //rxlifecycle 防止Activity关闭带来的内存泄漏
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<DownloadInfo>() {
@Override
public void call(DownloadInfo downloadInfo) {
processProgress(downloadInfo);
}
});
}
/**
*对进度更新后的数据在一个recycleView中进行显示
**/
private void processProgress(DownloadInfo downloadInfo) {
...
if (listAdapter != null) {
listAdapter.updateProgress(downloadInfo);
}
...
}
}
上述代码仅仅只写了Rxjava代码所需要编写的部分,从设计模式的角度出发,可以理解为在Service中定义了一个静态被观察者,并提供了这个被观察者的静态方法和触发这个被观察者事件,在Activity中获取这个被观察者后就进行订阅。省去了广播和Eventbus中很明显的需要注册和解除注册的环节,关于不解除注册可能带来的内存泄漏,在代码中已经使用rxlifecycle来进行解决了(rxlifecycle的相关介绍:https://blog.csdn.net/polo2044/article/details/80559390)
三、参考链接
https://www.cnblogs.com/Jason-Jan/p/8017412.html
https://www.jianshu.com/p/428a5257839c
https://www.jianshu.com/p/6f1ea19a17ed