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,官方已经停止对其进行更新了。
好了,不多说直接进入正题。
首先在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的实现和事例演示。