利用RxJava实现的事件总线(Event Bus)

概述

RxJava 在Android的APP开发中使用越来越广泛,其实不只是Android项目,java web方向的使用也越来越广泛。好多公司现在都开始引入RxJava和RxAndroid。RxJava对于开发效率,降低维护成本具有很大的作用。

RxJava采用的设计模式是典型的观察者模式,是一种响应式编程,支持链式操作。RxJava到底是什么?RxJava(RxJava在GitHub上的托管地址 )在 GitHub 主页上的自我介绍是 “a library for composing asynchronous and event-based programs using observable sequences for the Java VM”(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。这就是 RxJava ,概括得非常精准。其实也可以用一句话来归纳:RxJava是基于事件的异步java库

本篇不会对RxJava的使用做详细介绍,而是给有RxJava基础的同学介绍如何通过RxJava实现事件总线(Event Bus)。关于RxJava的使用建议大家自己先去看RxJava如何使用。现在对于RxJava的使用的相关文档也比较多,有许多还是不错的,除了官方的文档。推荐给还没有了解或者还没有使用过RxJava的同学一篇不错的RxJava入门教程(给Android开发者的RxJava详解)。这是一些开发爱好者共同编写的RxJava文档,写的非常的好。

对于事件总线,相信有很多Android开发人员都不陌生,一般有两种比较流行的,一种是Event Bus,另一种是otto。而otto已经被官方标记为deprecated,官方已经停止对其进行更新了。

RxBus的封装

好了,不多说直接进入正题。

首先在gradle中引入RxJava

compile 'io.reactivex:rxjava:1.1.5'

如果你是Android开发者,一般情况下,还需引入
compile 'io.reactivex:rxandroid:1.2.0'

先看一下RxBus的封装 RxBus

package com.syz.example;

import rx.Observable;
import rx.Subscription;
import rx.subjects.PublishSubject;
import rx.subjects.SerializedSubject;
import rx.subjects.Subject;

/** * Created by SYZ on 2016/11/10. */

public class RxBus {
    private static volatile RxBus instance = null;

    /** * PublishSubject只会把订阅发生的时间点之后来自原始Observable的数据发送给观察者 */
    private Subject<Object,Object> mRxBus = new SerializedSubject<>(PublishSubject.create());

    public static RxBus getInstance(){
        if (instance == null){
            synchronized (RxBus.class){
                if (instance == null){
                    instance = new RxBus();
                }
            }
        }
        return instance;
    }

    /** * 判断当前是否有可用的Observable * @return */
    private boolean hasObservable(){
        return mRxBus.hasObservers();
    }

    /** * 发送新的事件 * @param o */
    public void post(Object o){
        if (hasObservable()){
            mRxBus.onNext(o);
        }
    }

    /** * 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者 * @param eventType * @param <T> * @return */
    public <T> Observable<T> toObservable(Class<T> eventType){
        return mRxBus.ofType(eventType);
    }

    /** * 取消事件订阅 * @param subscription */
    public void unRegister(Subscription subscription){
        if (subscription !=null &&subscription.isUnsubscribed()){
            subscription.unsubscribe();
        }
    }

}

说明:
1、subject同时充当了Observer和Observable的角色,Subject是非线程安全的,要避免该问题,需要将 Subject转换为一个 SerializedSubject ,上述RxBus类中把线程非安全的PublishSubject包装成线程安全的Subject。

2、PublishSubject只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者。

3、ofType操作符只发射指定类型的数据。

有了事件总线我们还需要定义事件类型。至于事件类型,根据项目需要自定义。下面提供自定义事件类型的事例:EventType (设置和获取事件类型)和EventTypeConstants(自定义的事件类型常量,需要什么样的事件类型就在这个类中扩展即可)。

EventType

package com.syz.example.model;

/** * Created by SYZ on 2016/11/10. * <br><br> * 设置和获取事件类型 */

public class EventType {

    private String type;

    /** * 设置事件类型 * @param eventType */
    public void setEventType(String eventType){
        this.type = eventType;
    }

    /** * 获取事件类型 * @return */
    public String getEventType(){
        return type;
    }
}

EventTypeConstants

package com.syz.example.model;

/** * Created by SYZ on 2016/11/10. * <br><br> * 该类中主要是一些事件类型的常量。可以根据需要,添加事件类型 */

public class EventTypeConstants {
    /** * 事件类型列表,下面是自定义事件类型示例 */

    // 联系人信息发生改变事件
    public static final String EVENT_TYPE_CONTACT_CHANGE = "contact_change";

    // 服务器信息发生改变事件
    public static final String EVENT_TYPE_SERVER_DATA_CHANGE = "server_data_change";
}

根据上述封装的RxBus,提供事例demo测试一下:
布局文件:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">


    <data class=".RxJavaDataBinding">

        <import type="android.view.View" />

        <import type="com.syz.example.model.Student" />

        <variable  name="student" type="Student" />
    </data>

    <RelativeLayout  android:id="@+id/activity_rx_java" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.syz.example.rxjava.RxJavaActivity">

        <Button  android:id="@+id/test" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:background="@android:color/holo_blue_dark" android:onClick="onClick" android:text="联系人信息发生变化" android:textAllCaps="false" android:textColor="@android:color/white" />

        <Button  android:id="@+id/server_change" android:layout_below="@id/test" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:textAllCaps="false" android:text="服务器数据发生改变" android:onClick="onClick" android:background="@android:color/holo_blue_dark" android:textColor="@android:color/white"/>


        <LinearLayout  android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/search_data" android:gravity="center_horizontal" android:orientation="vertical">

            <TextView  android:id="@+id/stu_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text='@{student.name == null?"Default":student.name}' />

            <TextView  android:id="@+id/stu_sex" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text='@{student.sex == null?"male":student.sex}' />

            <TextView  android:id="@+id/stu_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text='@{student.studentNum == null?"001":student.studentNum}' />
        </LinearLayout>

    </RelativeLayout>
</layout>

RxJavaActivity

package com.syz.example.rxjava;

import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.syz.example.BaseActivity;
import com.syz.example.R;
import com.syz.example.RxBus;
import com.syz.example.RxJavaDataBinding;
import com.syz.example.model.EventType;
import com.syz.example.model.EventTypeConstants;
import com.syz.example.model.Student;

import rx.Subscription;
import rx.functions.Action1;

public class RxJavaActivity extends BaseActivity implements View.OnClickListener {

    private static final String TAG = "RxJavaActivity";

    private RxJavaDataBinding dataBinding;

    private Subscription rxSubscription;//订阅

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        dataBinding = DataBindingUtil.setContentView(this,R.layout.activity_rx_java);
        dataBinding.setStudent(new Student(007,"Tome","male","NB00121"));
        subscribe();
    }

    /** * 订阅事件 */
    private void subscribe(){
        rxSubscription = RxBus.getInstance().toObservable(EventType.class)
                .subscribe(new Action1<EventType>() {
                    @Override
                    public void call(EventType eventType) {
                        if (eventType.getEventType().equals(EventTypeConstants.EVENT_TYPE_CONTACT_CHANGE)) {
                            Toast.makeText(RxJavaActivity.this, "联系人信息发生变化", Toast.LENGTH_SHORT).show();
                        } else if (EventTypeConstants.EVENT_TYPE_SERVER_DATA_CHANGE.equals(eventType.getEventType())){
                            Toast.makeText(RxJavaActivity.this, "服务器数据发生变化", Toast.LENGTH_SHORT).show();
                        }
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        Log.e(TAG,"error = "+throwable.getMessage());
                    }
                });

    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.test:
                EventType eventType = new EventType();
                eventType.setEventType(EventTypeConstants.EVENT_TYPE_CONTACT_CHANGE);
                RxBus.getInstance().post(eventType);
                break;
            case R.id.server_change:
                EventType eventType2 = new EventType();
                eventType2.setEventType(EventTypeConstants.EVENT_TYPE_SERVER_DATA_CHANGE);
                RxBus.getInstance().post(eventType2);
                break;
            default:
                break;
        }
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        RxBus.getInstance().unRegister(rxSubscription);
    }
}

以上就是RxBus的实现和事例演示。

你可能感兴趣的:(rxjava,rxandroid,事件总线,Rxbus,BusEvent)