• [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/

  • 相关阅读:
    php的form中元素name属性相同时的取值问题
    从FCN到DeepLab
    论文学习:Fully Convolutional Networks for Semantic Segmentation
    笔记:基于DCNN的图像语义分割综述
    论文笔记(3):STC: A Simple to Complex Framework for Weakly-supervised Semantic Segmentation
    概念:弱监督学习
    FCN小小实战
    (2)Deep Learning之线性单元和梯度下降
    (1)Deep Learning之感知器
    深度学习实验系列(1)
  • 原文地址:https://www.cnblogs.com/tiantianbyconan/p/4578699.html
Copyright © 2020-2023  润新知