RxBus
通過(guò)RxJava實(shí)現(xiàn)Rxbus峡扩。
相信大家已經(jīng)非常熟悉EventBus了踱蠢。最近正在學(xué)習(xí)Rxjava汁汗,如果在項(xiàng)目中已經(jīng)使用了Rxjava撮抓,使用RxBus來(lái)代替EventBus應(yīng)該是不錯(cuò)的選擇妇斤。
RxJava最核心的兩個(gè)東西是Observables(被觀察者,事件源)和Subscribers(觀察者)丹拯。Observables發(fā)出一系列事件站超,Subscribers處理這些事件。
直接看代碼
Note that it is important to subscribe to the exact same rxBus instance that was used to post the events
采用單例模式來(lái)保證rxBus對(duì)象一致
public class RxBus {
private static RxBus rxBus;
private final Subject<Object, Object> _bus = new SerializedSubject<>(PublishSubject.create());
private RxBus() {
}
public static RxBus getInstance() {
if (rxBus == null) {
synchronized (RxBus.class) {
if (rxBus == null) {
rxBus = new RxBus();
}
}
}
return rxBus;
}
public void send(Object o) {
_bus.onNext(o);
}
public Observable<Object> toObserverable() {
return _bus;
}
}
Activity中發(fā)送事件
public void sendTap(View view){
RxBus.getInstance().send(new TapEvent());
}
public void sendOther(View view){
RxBus.getInstance().send(new OtherEvent());
}
Fragment中接收事件
RxBus.getInstance().toObserverable()
.subscribe(new Action1<Object>() {
@Override
public void call(Object o) {
if (o instanceof TapEvent) {
textView.setText("tap");
} else if (o instanceof OtherEvent) {
textView.setText("other");
}
}
});
效果
以上就是使用Rxjava簡(jiǎn)單實(shí)現(xiàn)RxBus的功能乖酬,當(dāng)然這還遠(yuǎn)遠(yuǎn)不夠
RxBus升級(jí)
在具體使用過(guò)程中總會(huì)碰到各種各樣的問(wèn)題
場(chǎng)景1
我在上一個(gè)項(xiàng)目中實(shí)現(xiàn)了無(wú)限輪播的功能死相,并且希望輪播圖在用戶滑動(dòng)、不可見(jiàn)咬像、以及程序在后臺(tái)休眠時(shí)都停止?jié)L動(dòng)算撮,這時(shí)候就希望EventBus及時(shí)的傳遞這3種狀態(tài),為此我需要寫(xiě)slideEvent县昂、visibleEvent肮柜、aliveEvent3個(gè)類,雖然他們都需要傳遞一個(gè)簡(jiǎn)單的Boolen值倒彰。
解決方案
創(chuàng)建一個(gè)Event“管家”
類似key-value的方式审洞,每個(gè)事件都有自己的唯一的Code,接收事件時(shí)根據(jù)Code返回對(duì)應(yīng)的content
public class Events<T> {
//所有事件的CODE
public static final int TAP = 1; //點(diǎn)擊事件
public static final int OTHER = 21; //其它事件
//枚舉
@IntDef({TAP, OTHER})
@Retention(RetentionPolicy.SOURCE)
public @interface EventCode {}
public @Events.EventCode int code;
public T content;
public static <O> Events<O> setContent(O t) {
Events<O> events = new Events<>();
events.content = t;
return events;
}
public <T> T getContent() {
return (T) content;
}
}
場(chǎng)景2
怎么又內(nèi)存泄漏了待讳?
每個(gè)人在開(kāi)發(fā)過(guò)程中芒澜,或多或少都會(huì)碰到內(nèi)存泄漏的的問(wèn)題,我一直有一個(gè)天真的想法创淡,RxJava那么牛逼痴晦,是不是能無(wú)聲無(wú)息地就能解決內(nèi)存泄漏的問(wèn)題了,答案是否定的琳彩。
我看了不少有關(guān)RxJava的文章誊酌,都會(huì)提到
一定要記得在生命周期結(jié)束的地方取消訂閱事件,防止RxJava可能會(huì)引起的內(nèi)存泄漏問(wèn)題汁针。
你可以
@Overrideprotected void onDestroy() {
super.onDestroy();
if(!rxSubscription.isUnsubscribed()) {
rxSubscription.unsubscribe();
}
}
又或者
使用CompositeSubscription把 Subscription 收集到一起术辐,方便 Activity(基類) 銷毀時(shí)取消訂閱砚尽,防止內(nèi)存泄漏施无。
前者可以在任一生命周期階段取消訂閱,缺點(diǎn)是每個(gè)acivity/fragment都要重寫(xiě)方法必孤。
后者可以寫(xiě)在BaseActivity(大家都不會(huì)陌生)猾骡,每個(gè)activity都能用瑞躺,缺點(diǎn)是不夠靈活。
以上兩種方法似乎都欠缺點(diǎn)意思兴想,所幸Rx家族“人丁興旺“”幢哨,早已想好了解決方案
RxLifecycle
一、bindToLifecycle()方法
在子類使用Observable中的compose操作符嫂便,調(diào)用捞镰,完成Observable發(fā)布的事件和當(dāng)前的組件綁定,實(shí)現(xiàn)生命周期同步毙替。從而實(shí)現(xiàn)當(dāng)前組件生命周期結(jié)束時(shí)岸售,自動(dòng)取消對(duì)Observable訂閱。
Observable.interval(1, TimeUnit.SECONDS)
.compose(this.bindToLifecycle())
.subscribe(new Action1<Long>() {
@Override
public void call(Long num) {
Log.i(TAG, " " +num);
}
});
二厂画、bindUntilEvent() 方法
使用ActivityEvent類凸丸,其中的CREATE、START袱院、 RESUME屎慢、PAUSE、STOP忽洛、 DESTROY分別對(duì)應(yīng)生命周期內(nèi)的方法腻惠。使用bindUntilEvent指定在哪個(gè)生命周期方法調(diào)用時(shí)取消訂閱。
public enum ActivityEvent {
CREATE,
START,
RESUME,
PAUSE,
STOP,
DESTROY
}
public enum FragmentEvent {
ATTACH,
CREATE,
CREATE_VIEW,
START,
RESUME,
PAUSE,
STOP,
DESTROY_VIEW,
DESTROY,
DETACH
}
組裝零件
public class RxBus {
private static RxBus rxBus;
private final Subject<Events<?>, Events<?>> _bus = new SerializedSubject<>(PublishSubject.<Events<?>>create());
private RxBus(){}
public static RxBus getInstance(){
if (rxBus == null){
synchronized (RxBus.class){
if (rxBus == null){
rxBus = new RxBus();
}
}
}
return rxBus;
}
public void send(Events<?> o) {
_bus.onNext(o);
}
public void send(@Events.EventCode int code, Object content){
Events<Object> event = new Events<>();
event.code = code;
event.content = content;
send(event);
}
public Observable<Events<?>> toObservable() {
return _bus;
}
public static SubscriberBuilder with(FragmentLifecycleProvider provider){
return new SubscriberBuilder(provider);
}
public static SubscriberBuilder with(ActivityLifecycleProvider provider){
return new SubscriberBuilder(provider);
}
public static class SubscriberBuilder{
private FragmentLifecycleProvider mFragLifecycleProvider;
private ActivityLifecycleProvider mActLifecycleProvider;
private FragmentEvent mFragmentEndEvent;
private ActivityEvent mActivityEndEvent;
private int event;
private Action1<? super Events<?>> onNext;
private Action1<Throwable> onError;
public SubscriberBuilder(FragmentLifecycleProvider provider) {
this.mFragLifecycleProvider = provider;
}
public SubscriberBuilder(ActivityLifecycleProvider provider){
this.mActLifecycleProvider = provider;
}
public SubscriberBuilder setEvent(@Events.EventCode int event){
this.event = event;
return this;
}
public SubscriberBuilder setEndEvent(FragmentEvent event){
this.mFragmentEndEvent = event;
return this;
}
public SubscriberBuilder setEndEvent(ActivityEvent event){
this.mActivityEndEvent = event;
return this;
}
public SubscriberBuilder onNext(Action1<? super Events<?>> action){
this.onNext = action;
return this;
}
public SubscriberBuilder onError(Action1<Throwable> action){
this.onError = action;
return this;
}
public void create(){
_create();
}
public Subscription _create(){
if (mFragLifecycleProvider!=null){
return RxBus.getInstance().toObservable()
.compose(mFragmentEndEvent == null ? mFragLifecycleProvider.bindToLifecycle() :mFragLifecycleProvider.<Events<?>>bindUntilEvent(mFragmentEndEvent)) // 綁定生命周期
.filter(new Func1<Events<?>, Boolean>() {
@Override
public Boolean call(Events<?> events) {
return events.code == event;
}
}) //過(guò)濾 根據(jù)code判斷返回事件
.subscribe(onNext, onError == null ? new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
} : onError);
}
if (mActLifecycleProvider!=null){
return RxBus.getInstance().toObservable()
.compose(mActivityEndEvent == null ? mActLifecycleProvider.bindToLifecycle() :mActLifecycleProvider.<Events<?>>bindUntilEvent(mActivityEndEvent))
.filter(new Func1<Events<?>, Boolean>() {
@Override
public Boolean call(Events<?> events) {
return events.code == event;
}
})
.subscribe(onNext, onError == null ? (Action1<Throwable>) new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
} : onError);
}
return null;
}
}
}
新BUS上路
依然使用前面的例子
Activity中發(fā)送事件
public void sendTap(View view){
RxBus.getInstance().send(Events.TAP, "Tap傳了一個(gè)String");
}
public void sendOther(View view){
RxBus.getInstance().send(Events.OTHER, null);
// RxBus.getInstance().send(Events.OTHER, new OtherEvent("Cloud", 25));
}
Fragment中接收事件
fragment需要繼承RxLifecycle對(duì)應(yīng)組件
public class BlankFragment extends RxFragment {}
RxBus.with(this)
.setEvent(Events.TAP)
// .setEndEvent(FragmentEvent.DESTROY_VIEW) //不設(shè)置默認(rèn)與fragment生命周期同步
.onNext(new Action1<Events<?>>() {
@Override
public void call(Events<?> events) {
String content = events.getContent();
textView.setText(content);
}
})
.create();
RxBus.with(this)
.setEvent(Events.OTHER)
.setEndEvent(FragmentEvent.DESTROY_VIEW) //不設(shè)置默認(rèn)與fragment生命周期同步
.onNext(new Action1<Events<?>>() {
@Override
public void call(Events<?> events) {
OtherEvent event = events.getContent();
textView.setText("Name: " + event.getName() + ",Age: "+ event.getAge());
}
})
.onError(new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
textView.setText(throwable.toString());
}
}) // 異常處理欲虚,默認(rèn)捕獲異常妖枚,不做處理,程序不會(huì)crash苍在。
.create();
效果
完整代碼绝页,請(qǐng)移步
參考資料
- FlowGeek:開(kāi)源中國(guó)Android客戶端MVP架構(gòu)Material Design設(shè)計(jì)風(fēng)格版
- Implementing an Event Bus With RxJava – RxBus:用RxJava實(shí)現(xiàn)EventBus