以下內容為原創,歡迎轉載,轉載請注明
來自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4578699.html
Github:https://github.com/wangjiegulu/RxAndroidEventsSample
EventBus的作用是發布/訂閱事件總線,因為項目中用到RxJava、RxAndroid,所以完全可以使用RxJava、RxAndroid來實現EventBus。
1. 編寫RxBus,用於存儲所有事件Subjects。
事件是傳遞的最小單位,可以把任何類作為一個事件。
RxBus代碼如下:
1 /** 2 * Author: wangjie 3 * Email: tiantian.china.2@gmail.com 4 * Date: 6/11/15. 5 */ 6 public class RxBus { 7 private static final String TAG = RxBus.class.getSimpleName(); 8 private static RxBus instance; 9 public static boolean DEBUG = false; 10 11 public static synchronized RxBus get() { 12 if (null == instance) { 13 instance = new RxBus(); 14 } 15 return instance; 16 } 17 18 private RxBus() { 19 } 20 21 private ConcurrentHashMap<Object, List<Subject>> subjectMapper = new ConcurrentHashMap<>(); 22 23 @SuppressWarnings("unchecked") 24 public <T> Observable<T> register(@NonNull Object tag, @NonNull Class<T> clazz) { 25 List<Subject> subjectList = subjectMapper.get(tag); 26 if (null == subjectList) { 27 subjectList = new ArrayList<>(); 28 subjectMapper.put(tag, subjectList); 29 } 30 31 Subject<T, T> subject; 32 subjectList.add(subject = PublishSubject.create()); 33 if (DEBUG) Log.d(TAG, "[register]subjectMapper: " + subjectMapper); 34 return subject; 35 } 36 37 public void unregister(@NonNull Object tag, @NonNull Observable observable) { 38 List<Subject> subjects = subjectMapper.get(tag); 39 if (null != subjects) { 40 subjects.remove((Subject) observable); 41 if (ABTextUtil.isEmpty(subjects)) { 42 subjectMapper.remove(tag); 43 } 44 } 45 46 if (DEBUG) Log.d(TAG, "[unregister]subjectMapper: " + subjectMapper); 47 } 48 49 public void post(@NonNull Object content) { 50 post(content.getClass().getName(), content); 51 } 52 53 @SuppressWarnings("unchecked") 54 public void post(@NonNull Object tag, @NonNull Object content) { 55 List<Subject> subjectList = subjectMapper.get(tag); 56 57 if (!ABTextUtil.isEmpty(subjectList)) { 58 for (Subject subject : subjectList) { 59 subject.onNext(content); 60 } 61 } 62 if (DEBUG) Log.d(TAG, "[send]subjectMapper: " + subjectMapper); 63 } 64 }
如上述代碼,RxBus只提供了register、unregister、post三個方法。
這里又加入了一個tag的概念,也可以理解為channel,注冊Subject、反注冊Subject和post事件的時候都需要這個tag,只有tag一致才能正常接收到事件。
比如有一個事件類HelloEvent,這個事件的作用是接收到后toast一個提示“hello”,如果兩個Activity都注冊了這個HelloEvent事件,但是沒有tag去限制,一旦post了一個helloEvent事件后,兩個Activity都會收到這個事件,導致兩個Activity都會toast。如果使用tag,post這個HelloEvent的時候可以設置這個tag,只有register時也使用了這個tag才會接收到這個event。
2. 在Present(如Activity的onCreate)中注冊一個Observer(以下以發送一個String類型的事件為例)
1 Observable<String> addOb = RxBus.get() 2 .register("addFeedTag", String.class); 3 4 addOb.observeOn(AndroidSchedulers.mainThread()) 5 .subscribe(s -> { 6 // todo: Accept event and process here 7 });
如上,注冊了一個String類型的事件,事件的tag是“addFeedTag”,用來增加一個Feed。使用RxAndroid在Action1中處理接收到的這個事件。
3. 在任何地方發送一個事件:
RxBus.get().post("addFeedTag", "hello RxBus!");
這里發送了一個tag為“addFeedTag”的String類型的事件。
4. 反注冊Observer:
RxBus.get().unregister("addFeedTag", addOb);
注意:這里的Tag都為“addFeedTag”。
下面使用注解的方式更簡單方便地使用RxBus(嗯-。-這里才是重點)。
首先來看下使用注解后的代碼:
1. 注冊Observer
這一步可以省略掉。
2. 發送一個事件(這里我們換一個事件:FeedItemClickEvent,我們定義這個事件是用來處理當Feed被點擊后的事件)
RxBus.get().post(new FeedItemClickEvent().setPosition(position).setFeed(feed));
3. 接收事件,然后處理
1 @Accept 2 public void onPostAccept(Object tag, FeedItemClickEvent event) { 3 Logger.d(TAG, "onPostAccept event: " + event); 4 Feed feed = event.getFeed(); 5 // 跳轉到feed詳情頁面... 6 }
如上,這里只需要編寫一個方法,加上Accept注解,然后在方法中進行事件處理即可。
注意:方法名可以任意
方法參數一:必須為Object類型的tag;
方法參數二,如果這個方法只接收一種事件,則寫明具體的事件類型,如上;如果這個方法接收多種事件,則類型需要為Object。
4. 反注冊Observer
這一步也可以省略掉。
接收多種事件:
1 @Accept( 2 acceptScheduler = AcceptScheduler.NEW_THREAD, 3 value = { 4 @AcceptType(tag = ActionEvent.CLOSE, clazz = String.class), 5 @AcceptType(tag = ActionEvent.BACK, clazz = String.class), 6 @AcceptType(tag = ActionEvent.EDIT, clazz = String.class), 7 @AcceptType(tag = ActionEvent.REFRESH, clazz = String.class) 8 } 9 ) 10 public void onPostAccept(Object tag, Object actionEvent) { 11 Logger.d(TAG, "[ActionEvent]onPostAccept action event name: " + actionEvent); 12 // todo: Accept event and process here (in new thread) 13 }
這里@Accept注解中設置了acceptScheduler為AcceptScheduler.NEW_THREAD,指明方法運行在子線程中.
value中指明了接收的事件類型,這里表示這個方法接收4種類型的事件:CLOSE, BACK, EDIT, REFRESH.
注解解釋:
@Accept注解
acceptScheduler: 指定被注解的方法運行的Scheduler。
value[]: AcceptType注解數組,用於指定接收事件的tag和class。
@AcceptType注解:
tag: 接收事件的tag
clazz: 接收事件的類型
AcceptScheduler:
詳情見:rx.schedulers.Schedulers和rx.android.schedulers.AndroidSchedulers
如果設置的是AcceptScheduler.EXECUTOR或AcceptScheduler.HANDLER,則需要在Application中配置Executor和Handler:
1 /** 2 * Author: wangjie 3 * Email: tiantian.china.2@gmail.com 4 * Date: 6/15/15. 5 */ 6 public class MyApplication extends Application { 7 private Executor acceptExecutor = Executors.newCachedThreadPool(); 8 private Handler handler = new Handler(Looper.getMainLooper()); 9 10 @Override 11 public void onCreate() { 12 super.onCreate(); 13 RxBus.DEBUG = true; 14 15 DefaultAcceptConfiguration.getInstance().registerAcceptConfiguration(new DefaultAcceptConfiguration.OnDefaultAcceptConfiguration() { 16 @Override 17 public Executor applyAcceptExecutor() { 18 return acceptExecutor; 19 } 20 21 @Override 22 public Handler applyAcceptHandler() { 23 return handler; 24 } 25 }); 26 } 27 }
因為需要對Accept和AcceptType注解的解析,所以項目的BaseActivity需要使用AIAppCompatActivity,然后實現parserMethodAnnotations()方法,使用RxBusAnnotationManager對注解進行解析。
參考:http://nerds.weddingpartyapp.com/tech/2014/12/24/implementing-an-event-bus-with-rxjava-rxbus/