[Android]基於RxJava、RxAndroid的EventBus實現


以下內容為原創,歡迎轉載,轉載請注明

來自天天博客: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/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM