为什么要用RxJava
因为项目里用到了RxJava,所以最近开始接触它,接触第一天简直是一脸懵逼啊,但是在看了二十几遍“大头鬼Bruce”和“仍物线”的对于RxJava的讲解后,发现RxJava真是太棒了!它其中的链式编程颠覆了我们之前的命令式编程的思想,其最大的好处就是简洁,程序在不断变复杂的情况下,它依然可以保持简洁和很高的可读性。
RxJava是什么
RxJava 的本质可以压缩为异步这一个词。说到根上,它就是一个实现异步操作的库,而别的定语都是基于这之上的。
RxJava的几个基本概念:
- Observable:被观察者
- Observer:观察者
- subscribe:订阅
Observable 和 Observer 通过 subscribe() 方法实现订阅关系,对于初学者来说,刚开始的时候可能和我一样,对于订阅这个词的理解不太到位,慢慢的我觉得它更像是一种关系,类似于绑定、注册等,比如A和B之间通过订阅产生了一种关系。
Hello World
其实,对于初学者来说,写一个RxJava的Hellp World并不难,只需要三步就可以搞定:
- 一、创建Observable
- 二、创建Observer
- 三、将Observable 和 Observer 通过 subscribe() 方法实现订阅关系
下面我们一起来写一下
- 创建Observable,创建一个Observable对象很简单,直接调用Observable.create即可
Observable<String> myObservable = Observable.create(
new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> sub) {
sub.onNext("Hello, world!");
sub.onCompleted();
}
}
);
2.这里定义的Observable对象仅仅发出一个Hello World字符串,然后就结束了。接着我们创建一个Subscriber来处理Observable对象发出的字符串。
Observer<String> observer = new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
textView.setText(s);
}
});
3.将Observable 和 Observer 通过 subscribe() 方法实现订阅关系:
myObservable.subscribe(observer);
OK,大功告成,此时我们就可以输出Hello, world!了。
简化代码
其实上面的代码我们可以简化为一行:
Observable<String> myObservable = Observable.just("Hello, world!");
简单吧!
Subscriber
除了 Observer 接口之外,RxJava 还内置了一个实现了 Observer 的抽象类:Subscriber。 Subscriber 对 Observer 接口进行了一些扩展,但他们的基本使用方式是完全一样的:
Subscriber<String> mySubscriber = new Subscriber<String>() {
@Override
public void onNext(String s) { System.out.println(s); }
@Override
public void onCompleted() { }
@Override
public void onError(Throwable e) { }
};
它们的区别对于使用者来说主要有两点:
onStart(): 这是 Subscriber 增加的方法。它会在 subscribe 刚开始,而事件还未发送之前被调用,可以用于做一些准备工作,例如数据的清零或重置。这是一个可选方法,默认情况下它的实现为空。需要注意的是,如果对准备工作的线程有要求(例如弹出一个显示进度的对话框,这必须在主线程执行), onStart() 就不适用了,因为它总是在 subscribe 所发生的线程被调用,而不能指定线程。要在指定的线程来做准备工作,可以使用 doOnSubscribe() 方法,具体可以在后面的文中看到。
unsubscribe(): 这是 Subscriber 所实现的另一个接口 Subscription 的方法,用于取消订阅。在这个方法被调用后,Subscriber 将不再接收事件。一般在这个方法调用前,可以使用 isUnsubscribed() 先判断一下状态。 unsubscribe() 这个方法很重要,因为在 subscribe() 之后, Observable 会持有 Subscriber 的引用,这个引用如果不能及时被释放,将有内存泄露的风险。所以最好保持一个原则:要在不再使用的时候尽快在合适的地方(例如 onPause() onStop() 等方法中)调用 unsubscribe() 来解除引用关系,以避免内存泄露的发生。
Action的引入
我们看到,上面的代码有时我们可能并不关系OnComplete和OnError,这时我们就可以用到Action1。最后的代码可以写成如下:
Observable.just("Hello, world!")
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
System.out.println(s);
}
});
有Action1当然会有Action0,它们的区别主要在与Action1是有参数的,可以替换onNext和OnComplete;而Aciton0是无参的,可以替换OnError
线程控制
因为RxJava 的本质可以压缩为异步,所以在RxJava中,线程的切换必不可少,控制线程的方法有两种:subscribeOn和observeOn。这里我就不细讲了,贴一段用法的代码,具体的区别可以看上面链接的文章.
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("123");
subscriber.onCompleted();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
textView.setText(str);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
textView.setText("错误!");
}
}, new Action0() {
@Override
public void call() {
}
});
初识简单操作符
RxJava之所以灵活多遍,可以适用在很多场景,操作符算是头功。操作符主要解决了对Observable对象的变换的问题,用于在Observable和最终的Subscriber之间修改Observable发出的事件。像上面用到的just,create,它们都属于操作符。常用的操作符还有map、flatmap、concat、zip等等,这里说几个简单的,具体操作符介绍大全可以看这篇文章:http://blog.chinaunix.net/uid-20771867-id-5187376.html 大神写的非常非常全。
map
首先看一段代码:
Observable.just("a")
.map(new Func1<String, Integer>() {
@Override
public Integer call(String s) {
return s.hashCode();
}
})
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer s) {
System.out.print(Integer.toString(s));
}
});
你猜的没错,最后的输出结果为a的hashCode码97。所以,我们可以想到,map()的作用为:
用于变换Observable对象,map操作符返回一个Observable对象,这样就可以实现链式调用,在一个Observable对象上多次使用map操作符,最终将最简洁的数据传递给Subscriber对象。
first
同样的,我们再看一段代码:
Observable.just(1,2,3,4,5,6,7,8)
.first()
.subscribe(new Subscriber<Integer>() {
@Override
public void onNext(Integer item) {
System.out.println("Next: " + item);
}
@Override
public void onError(Throwable error) {
System.err.println("Error: " + error.getMessage());
}
@Override
public void onCompleted() {
System.out.println("Sequence complete.");
}
});
输出结果为:
Next: 1
Sequence complete.
因此,first的作用为:first操作符是把源Observable产生的结果的第一个提交给订阅者,注意:这里的第一个并不一定是数字上的第一个,而是符合输出条件的第一个,看一下下面的例子:
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
subscriber.onNext(1);
subscriber.onNext(2);
subscriber.onNext(3);
subscriber.onCompleted();
}
}).first(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
return integer > 2;
}
}).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.print(integer);
}
});
这个例子最终的输出结果为3,这下明白了吧。好了,操作符合就暂时举这两个例子,更多的大家可以看上面的链接,以后我有时间的话会专门再写一篇操作符的文章。
好了,这就是我对RxJava的初步理解,有写的不好的地方请大家多多指教。最后附上一个我自己写的很简单的demo,代码很简单,但是对于初学者来说都是很经典的东西:
http://download.youkuaiyun.com/detail/dzx997681136/9654805
“大头鬼Bruce”和“仍物线”两位大神的RxJava的介绍给了我很大的帮助,附上两篇文章的链接:
http://gank.io/post/560e15be2dca930e00da1083#toc_10
http://blog.youkuaiyun.com/lzyzsd/article/details/41833541/