學習資料
- YoKey大神:用RxJava實現事件總線(Event Bus)
- 謝三弟大神:從 RxBus 這輛蘭博基尼深入進去
1. RxJava1.0版本使用
RxJava 2.0
版本與1.0
有些不同
1.1 RxBus簡單實現
主要用于發送
和接收
public class RxBus {
private final Subject<Object, Object> bus;
private static RxBus defaultRxBus;
private RxBus() {
bus = new SerializedSubject<>(PublishSubject.create());
}
public static RxBus getInstance() {
if (null == defaultRxBus) {
synchronized (RxBus.class) {
if (null == defaultRxBus) {
defaultRxBus = new RxBus();
}
}
}
return defaultRxBus;
}
/*
* 發送
*/
public void post(Object o) {
bus.onNext(o);
}
/*
* 是否有Observable訂閱
*/
public boolean hasObservable() {
return bus.hasObservers();
}
/*
* 轉換為特定類型的Obserbale
*/
public <T> Observable<T> toObservable(Class<T> type) {
return bus.ofType(type);
}
}
post()
方法就是使用onNext(Object o)
方法,將Event對象
發送出去
toObservable(Class<T> type)
,轉換為特定類型的Obserbale。方法內使用了ofType
操作符,ofType
源碼內就是filter + cast
的組合,只發送特定的類型。fliter
用來判斷是否為指定的類型,cast
將一個Observable
轉換為指定的特殊Observable
1.2 Activity中使用
最簡單的使用,只是為了使用而使用,沒有考慮任何場景
public class RxBusActivity extends AppCompatActivity {
private CompositeSubscription mCom;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rx_bus);
initView();
}
private void initView() {
tv = (TextView) findViewById(R.id.rxbus_activity_tv);
Button button = (Button) findViewById(R.id.rxbus_activity_send);
//點擊發送事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RxBus.getInstance().post(new Event("RxBus Info!!!"));
}
});
//接收
mCom = new CompositeSubscription();
//Event 類型的 Observable 訂閱
Subscription subscription = RxBus.getInstance().toObservable(Event.class).subscribe(new Action1<Event>() {
@Override
public void call(Event event) {
tv.setText(event.info);
}
});
//將 Subscription 添加進 CompositeSubscription中
mCom.add(subscription); }
class Event {
String info;
Event(String info) {
this.info = info;
}
}
// @Override
// protected void onDestroy() {
// super.onDestroy();
// if (null != mCom && !mCom.isUnsubscribed()) {
// mCom.unsubscribe();
// }
// }
}
Activity
中有一個Button
,點擊Button
后發送一個攜帶字符串RxBus Info!!!
的Event
對象
CompositeSubscription
看作是用來收集Subscription
容器,內部有一個new HashSet<Subscription>(4)
1.2.1 未取消訂閱發生內存泄漏
當成功接收到字符串信息后,點擊返回鍵,關閉當前使用了RxBus
接收Event
的Activity
,過了5秒鐘左右,使用的LeakCanary
,便給出了內存泄漏信息
原因:未取消訂閱
@Override
protected void onDestroy() {
super.onDestroy();
if (null != mCom && !mCom.isUnsubscribed()) {
mCom.unsubscribe();
}
}
記得在onDestory()
取消訂閱,CompositeSubscription
會將內部所有的Subscription
取消訂閱
1.3 認識車零件
在RxBus
中涉及到3個重要零件
- Subject
橋梁或者代理;既是Observable
又是Observer
。作為一個Observer
,可以被一個或多個Observable
進行subscribe訂閱
;作為一個Observable
,可以轉發收到(Observe)的數據,也可以發射新的數據
- SerializedSubject
把 Subject
當作一個 Subscriber
使用時,注意不要從多個線程中調用它的onNext()
方法,也包括其它的onXX()
系列方法。這可能導致同時(非順序)調用,這會違反Observable
協議,給Subject
的結果增加了不確定性。需要將Subscriber
轉換為一個SerializedSubject
mySafeSubject = new SerializedSubject( myUnsafeSubject )
- PublishSubject
只會把在訂閱發生的時間點之后來自原始Observable
的數據發送給Observer
PublishSubject
可能會一創建完成,就開始發送數據。這可能會導致在Subject
被創建到有觀察者訂閱它之前這個時間段內,有數據丟失。為了確保原始Observable
的所有數據都被分發,可以使用PublishSubject.create()
,以便手動給它引入冷Observable
的行為,也就是當所有觀察者都已經訂閱時才開始發射數據
2. RxJava2.0版本
2.0
版本的RxBus
有些改動,但代碼實現思路應該還是一樣的。
RxJava1.0
都只是了解一些基礎,2.0
更不了解,需要再學習很長一段時間
2.1 RxBus2
代碼:
public class RxBus2 {
private static RxBus2 defaultRxBus;
private Subject<Object> bus;
private RxBus2() {
bus = PublishSubject.create().toSerialized();
}
public static RxBus2 getInstance() {
if (null == defaultRxBus) {
synchronized (RxBus2.class) {
if (null == defaultRxBus) {
defaultRxBus = new RxBus2();
}
}
}
return defaultRxBus;
}
public void post(Object o){
bus.onNext(o);
}
public boolean hasObservable() {
return bus.hasObservers();
}
/*
* 轉換為特定類型的Obserbale
*/
public <T> Observable<T> toObservable(Class<T> type) {
return bus.ofType(type);
}
}
SerializedSubject
不再通過直接new
的方式,而是使用PublishSubject.create().toSerialized()
的方式
2.2 Activity使用
代碼:
public class RxBus2Activity extends AppCompatActivity {
private TextView textView;
private CompositeDisposable compositeDisposable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rx_bus2);
initView();
}
private void initView() {
textView = (TextView) findViewById(R.id.rx_activity_tv);
Button button = (Button) findViewById(R.id.rx_activity_bt);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RxBus2.getInstance().post(new Event("RxBus2 Info!!!"));
}
});
compositeDisposable = new CompositeDisposable();
RxBus2.getInstance().toObservable(Event.class).subscribe(new Observer<Event>() {
@Override
public void onSubscribe(Disposable d) {
compositeDisposable.add(d);
}
@Override
public void onNext(Event event) {
textView.setText(event.info);
}
@Override
public void onError(Throwable e) {
textView.setText(e.getMessage());
}
@Override
public void onComplete() {
}
});
}
class Event {
String info;
Event(String info) {
this.info = info;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (null != compositeDisposable && !compositeDisposable.isDisposed()) {
compositeDisposable.clear();
}
}
}
subscribe()訂閱
方法返回值為void
,不再是Subscription
。而取消訂閱的控制權則交給了
onSubscribe(Disposable d)
方法中的Disposable
。使用CompositeDisposable
可以將所有的訂閱關系清除
3. 最后
過完年,第一篇博客,哈哈。看到朋友圈都在曬2017第一個工作日,作為一個沒有找到工作的人,表示各種羨慕
有錯誤,請指出
共勉 :)