什么是RxJava?RxJava 在 GitHub上的自我介绍是 “a library for composing asynchronous and event-based programs using observable sequences for the Java VM”(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。这就是 RxJava。
接下来不多说什么了,直接进入今天的主题吧
RxJava的API使用,包括Observable的创建,以及变换,以及数据的过滤等
Observable的创建有几种方式,比如create,just,from,interval,timer
1.1 create方法,是Rxjava中创建Observable最基本的方法,例子如下-创建Observable时,传入onSubsribe作为参数,会被存储在Observable对象中,当Observable被订阅时,就会触发其call方法。
private void testRxMethod_create() {
Observable observable = Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super RxBeanInfo> subscriber) {
RxBeanInfo info = new RxBeanInfo();
info.setName("lqm.test");
subscriber.onNext(info);
subscriber.onCompleted();
}});
Subscriber subscriber = new Subscriber()
{
@Override
public void onCompleted() {
Log.i("rxjava", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i("rxjava", "error");
}
@Override
public void onNext(RxBeanInfo o) {
Log.i("rxjava", o.getName());
}};
//通过调用subscribe方法使观察者和订阅者产生关联,一旦订阅,Observable就会调用call().
observable.subscribe(subscriber);
}
11-17 14:27:14.513 14944-14944/pa.test.com.testapp I/rxjava: lqm.test
11-17 14:27:14.513 14944-14944/pa.test.com.testapp I/rxjava: onCompleted
1.2.just—通过调用just方法,传入你想发送的数据源,当订阅者进行订阅的时候就开始打印数据,需要注意的是,just()方法最多可传10个参数,它们会按照传入的参数的顺序来发射它们
private void testRxMethod_just() {
Observable observable = Observable.just("1", "2", "3","4", "5","6","7","8","9","10");
Subscriber subscriber = new Subscriber()
{
@Override
public void onCompleted() {
Log.i("rxjava", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i("rxjava", "error");
}
@Override
public void onNext(String o) {
Log.i("rxjava", o);
}};
observable.subscribe(subscriber);
}
1.3.from—该方法参数是一个数组,然后from会将其拆分为一个个对象,发射出去
private void testRxMethod_from() {
List items = new ArrayList<>();
items.add("1");
items.add("2");
items.add("3");
Observable observable = Observable.from(items);
Subscriber subscriber = new Subscriber()
{
@Override
public void onCompleted() {
Log.i("rxjava", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i("rxjava", "error");
}
@Override
public void onNext(String o) {
Log.i("rxjava", o);
}};
observable.subscribe(subscriber);
}
11-17 14:44:13.043 30921-30921/pa.test.com.testapp I/rxjava: 1
11-17 14:44:13.043 30921-30921/pa.test.com.testapp I/rxjava: 2
11-17 14:44:13.043 30921-30921/pa.test.com.testapp I/rxjava: 3
11-17 14:44:13.043 30921-30921/pa.test.com.testapp I/rxjava: onCompleted
1.4.interval-定时器,该方法会每隔一段时间发射消息,interval()函数的两个参数:一个指定两次发射的时间间隔,另一个是用到的时间单位。
private void testRxMethod_interval() {
Observable.interval(2, TimeUnit.SECONDS)
.subscribe(new Observer() {
@Override
public void onCompleted() {
Log.i("rxjava", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i("rxjava", "onError");
}
@Override
public void onNext(Long number) {
Log.i("rxjava", "onNext"+number);
}
});
}
1.5.timer—可达到延时器效果之用,订阅后,Observable发射出一个0,就结束了,调用 onCompleted().
private void testRxMethod_timer() {
Observable.timer(3,TimeUnit.SECONDS)
.subscribe(new Observer() {
@Override
public void onCompleted() {
Log.i("rxjava", "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i("rxjava", "onError");
}
@Override
public void onNext(Long number) {
Log.i("rxjava", "onNext"+number);
}
});
}
2.Observable变换以及过滤
2.1.map—是对对象的一种直接变换函数,它会接受一个Fun函数当作入参,然后将它应用到每一个由Observable发射的值上,它将输入的数据处理后,返回一种新形式的数据,可以是任一类型。应用场景可以是:将图片路径(String)处理后返回Bitmap图片,或者计算原始数据,处理后成为需要的数据。
private void testRxMethod_map() {
Observable.just(6)
.map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
return integer/3+"";
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.d("lqm","call:"+s);
}
});
}
2.2.flatMap—Observable.flatMap()接收一个Observable的输出作为输入,同时输出另外一个Observable。
private void testRxMethod_flatMap() {
Observable.just("girl;boy;man")
.flatMap(new Func1>() {
@Override
public Observable call(String s) {
return Observable.from(s.split(";"));
}
})
.subscribe(new Action1() {
@Override
public void call(String s) {
Log.d("lqm", "onNext:" + s);
}
}, new Action1() {
@Override
public void call(Throwable throwable) {
Log.d("lqm", "onerror");
}
}, new Action0() {
@Override
public void call() {
Log.d("lqm", "onComplete");
}
});
}
11-17 15:41:04.743 18653-18653/pa.test.com.testapp D/lqm: onNext:girl
11-17 15:41:04.743 18653-18653/pa.test.com.testapp D/lqm: onNext:boy
11-17 15:41:04.743 18653-18653/pa.test.com.testapp D/lqm: onNext:man
11-17 15:41:04.743 18653-18653/pa.test.com.testapp D/lqm: onComplete
要对比下flatMap跟map,flatMap传入的参数是Observable,返回的也是 Observable,虽然两者都是传入一个对象,再转化成一个新对象,但是这一点还是很有区别的,关于flatMap的原理,这边引用下扔物线的一段话来解释:flatMap() 的原理是这样的:1. 使用传入的事件对象创建一个 Observable 对象;2. 并不发送这个 Observable, 而是将它激活,于是它开始发送事件;3. 每一个创建出来的 Observable 发送的事件,都被汇入同一个 Observable ,而这个 Observable 负责将这些事件统一交给 Subscriber 的回调方法。
2.3filter—过滤方法,使用这个方法来过滤掉一些我们不需要的数据,返回false,说明该对象不符合要求,会被过滤; 返回true,说明该对象可以正常往下走,符合标准。
private void testRxMethod_filter() {
String[] strArr = {"a123","b123","c123","d123"};
Observable.from(strArr)
.filter(new Func1() {
@Override
public Boolean call(String s) {
return s.contains("a") || s.contains("b") || s.contains("c");
}
})
.subscribe(new Action1() {
@Override
public void call(String s) {
Log.d("lqm","call:"+s);
}
});
}
11-17 20:39:54.761 32378-32378/pa.test.com.testapp D/lqm: call:a123
11-17 20:39:54.761 32378-32378/pa.test.com.testapp D/lqm: call:b123
11-17 20:39:54.761 32378-32378/pa.test.com.testapp D/lqm: call:c123
2.4 distinct—在一个序列中去掉重复数据
private void testRxMethod_distinct() {
Observable.just("Jack", "Honey","Lucy","Lucy","Jane")
.distinct().subscribe(new Subscriber() {
@Override
public void onCompleted() {
Log.i("lqm","onCompleted");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
Log.i("lqm","onNext" + s);
}
});
}
11-17 20:47:00.141 19536-19536/pa.test.com.testapp I/lqm: onNextJack
11-17 20:47:00.141 19536-19536/pa.test.com.testapp I/lqm: onNextHoney
11-17 20:47:00.141 19536-19536/pa.test.com.testapp I/lqm: onNextLucy
11-17 20:47:00.141 19536-19536/pa.test.com.testapp I/lqm: onNextJane
11-17 20:47:00.141 19536-19536/pa.test.com.testapp I/lqm: onCompleted
这边需要注意的是,distinct只能区别基本类型的重复以及是否同一对象,若是不同对象内容相同,是不能去重的
private void testRxMethod_distinct() {
RxBeanInfo info1 = new RxBeanInfo();
info1.setName("jack");
RxBeanInfo info2 = new RxBeanInfo();
info2.setName("jack");
RxBeanInfo info3 = new RxBeanInfo();
info3.setName("jack");
Observable.just(info1,info2,info3)
.distinct().subscribe(new Subscriber() {
@Override
public void onCompleted() {
Log.i("lqm","onCompleted");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(RxBeanInfo s) {
Log.i("lqm","onNext" + s.getName());
}
});
}
11-17 20:50:01.101 25465-25465/pa.test.com.testapp I/lqm: onNextjack
11-17 20:50:01.101 25465-25465/pa.test.com.testapp I/lqm: onNextjack
11-17 20:50:01.101 25465-25465/pa.test.com.testapp I/lqm: onNextjack
11-17 20:50:01.101 25465-25465/pa.test.com.testapp I/lqm: onCompleted
这些API是比较常用了,目前就讲到这些,如果有兴趣的,可以去给Android开发者的RxJava 详解去细看。
这边主要介绍的是RxJava 的 Schedulers(调度器) 功能
对于任何 Observable 你可以定义在两个不同的线程。
1. 使用 Observable.observeOn() 可以定义在一个线程上,可以用来监听和检查从 Observable 最新发出的 items (Subscriber 的 onNext,onCompleted 和 onError 方法会执行在 observeOn 所指定的线程上)。
2. 使用 Observable.subscribeOn() 来定义一个线程,subscribeOn() 指定 subscribe() 所发生的线程,即 Observable.OnSubscribe 被激活时所处的线程。
RxJava 默认情况下是单线程的,你会需要利用 observeOn() 和 subscribeOn() 方法为你的应用带来多线程操作。RxJava 附带了几个现成的 Schedulers 给 Observables 使用,如:Schedulers.io() (用于 I/O 操作),Schedulers.computation()(计算工作),和 Schedulers.newThread()(为任务创建的新线程),另外, Android 还有一个专用的 AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行。
了解到这些,我们来看看实际Rxjava是在线程间是如何运行的,这边会分case 来详解
1.只配置了 observeOn,但是在不同的位置,会有什么样的影响呢?
private void observableEvent() {
Log.d("lqm","mainthread :"+android.os.Process.myTid());
Observable.just(1)
.map(new Func1() {
@Override
public String call(Integer integer) {
Log.d("lqm","map:"+android.os.Process.myTid());
return integer+"a";
}
})
.filter(new Func1() {
@Override
public Boolean call(String s) {
Log.d("lqm","filter:"+android.os.Process.myTid());
return s.contains("1");
}
})
.observeOn(Schedulers.io())
.subscribe(new Action1() {
@Override
public void call(String s) {
Log.d("lqm","call:"+android.os.Process.myTid());
}
});
}
11-17 21:08:58.551 7624-7624/pa.test.com.testapp D/lqm: mainthread :7624
11-17 21:08:58.591 7624-7624/pa.test.com.testapp D/lqm: map:7624
11-17 21:08:58.591 7624-7624/pa.test.com.testapp D/lqm: filter:7624
11-17 21:08:58.591 7624-8857/pa.test.com.testapp D/lqm: call:8857
从上面运行结果可以看出,主线程id为7624,map()和filter()运行在主线程,由于调用subscribe()时调用了observeOn(Schedulers.io()),所以call()方法运行在io线程上。
那如果我们将observeOn()提前呢,会不会对线程造成影响呢?
private void observableEvent() {
Log.d("lqm","mainthread :"+android.os.Process.myTid());
Observable.just(1)
.observeOn(Schedulers.io())
.map(new Func1() {
@Override
public String call(Integer integer) { Log.d("lqm","map:"+android.os.Process.myTid());
return integer+"a";
}
})
.filter(new Func1() {
@Override
public Boolean call(String s) { Log.d("lqm","filter:"+android.os.Process.myTid());
return s.contains("1");
}
})
.subscribe(new Action1() {
@Override
public void call(String s) { Log.d("lqm","onNext:"+android.os.Process.myTid());
}
});
}
11-18 10:02:35.691 21563-21563/pa.test.com.testapp D/lqm: mainthread :21563
11-18 10:02:35.711 21563-22093/pa.test.com.testapp D/lqm: map:22093
11-18 10:02:35.711 21563-22093/pa.test.com.testapp D/lqm: filter:22093
11-18 10:02:35.711 21563-22093/pa.test.com.testapp D/lqm: onNext:22093
看到了没有,现在map(),filter()和onNext()都运行在IO线程上了
所以目前来看,observeOn()对除了Subscriber操作产生影响,还对map,filter等产生影响,但是只会对ObserveOn()操作后的动作产生影响
接下来继续测试。