上篇博客遗留了一个问题,既然是RxJava异步的,为什么是先执行先点击的,然后执行后点击的呢?这就引出了我们今天要说的另一个问题:异步线程
subscribeOn就是用于
指定监听时所发生的线程,我们进去看下源码情况
由注释可以看出这是这是一个异步操作,并且由ObservableSubscribeOn实现。知道了原理我们来实现一下,修改一下代码
Observable.create(ObservableOnSubscribe<String> { emitter ->
try {
var i = 0
while (i < 10) {
emitter.onNext("数据$i")
Thread.sleep(1000)
i++
}
emitter.onComplete()
} catch (e: InterruptedException) {
Log.e(TAG, "onNext:${e.toString()} ")
}
}).subscribeOn(Schedulers.newThread()).subscribe(object : Observer<String> {
override fun onComplete() {
}
override fun onError(e: Throwable) {
}
override fun onNext(t: String) {
Log.d(TAG, "onNext:$t")
}
override fun onSubscribe(d: Disposable) {
}
})
}
再次点击,打开日志看输出情况
好像并不是特别完美,并没有按照我们预想的发送事件,聪明的你一定猜到了,对了,我们建立了一个新的线程发送,但是我们并没有用线程接受啊,所以肯定还是不行的!
observeOn
observeOn就是用于指定接受的回调发生的线程,我们再次修改我们的代码
再次运行,然后打开日志看看情况
可以看到已经达到我们预期的效果了
说了这么多我们传递的都是字符串,数字这种类型的数据,假如我们想传递图片该怎么办呢?其实也很简单,原理跟前面一样,只需要把传递的类型改为Bitmap然后接受的类型也改为Bitmap就可了,我们看一下代码:
Observable<Bitmap> observableBitmap = Observable.create(new ObservableOnSubscribe<Bitmap>() {
@Override
public void subscribe(ObservableEmitter<Bitmap> emitter) {
File file = new File(Environment.getExternalStorageDirectory().getPath() + "/tt.jpg");
if (file.exists()) {
Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getPath() + "/tt.jpg");
emitter.onNext(bitmap);
}
emitter.onComplete();
}
});
这是一个传递图片的Observable,会有人问你的接收器在哪里,我传递了没法接收啊,你先别急,我们往下看。像上面例子那么些肯定是可以的,但是充斥在各个类中管理起来就不是那么方便了,我们把它抽调出来,统一管理,在需要的时候去调用,这样在需要的时候就几乎不费什么时间就可以修改,对程序员来说,时间就是金钱。怎么调用呢,跟以前一样,只不过有稍稍的改变,上代码,我还是喜欢以代码说话,因为不知道怎么说,看看效果如何(要注意权限哦)
observableBitmap.subscribe(object : Observer<Bitmap> {
override fun onSubscribe(d: Disposable) {
}
override fun onNext(t: Bitmap) {
rxImage.setImageBitmap(t)
}
override fun onComplete() {
Log.d(TAG, "onNext:Complete");
}
override fun onError(e: Throwable) {
Log.d(TAG, "onNext:${e.toString()}");
}
})
已经正常显示出来了
我们在延申一下,假如我不知道数据是什么类型,那我们怎么传递呢?其实也很简单,既然不知道,那就传递一个对象呗,修改下代码,我新建了一个实体类,然后传递
Observable observableT = Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter emitter) throws Exception {
int i = 0;
while (i < 3) {
RxJavaBean rxJavaBean = new RxJavaBean(i, "name" + i, i + 20);
emitter.onNext(rxJavaBean);
i++;
}
emitter.onComplete();
}
});
同理接收
observableT.subscribe(object : Observer<Any> {
override fun onSubscribe(d: Disposable) {
}
override fun onNext(t: Any) {
var rejavaBean = t as RxJavaBean
Log.d(TAG, "onNext:${rejavaBean.name}${rejavaBean.age}");
}
override fun onComplete() {
Log.d(TAG, "onNext:Complete");
}
override fun onError(e: Throwable) {
Log.d(TAG, "onNext:${e.toString()}");
}
})
查看结果
是不是很简单,到这里RxJava的功能就差不多完结了
简单说下Map和FlatMap吧,简单来说两个方法的作用就是转换,将你传入的值转换成另一种形式传递出去,例如将一个图片路径传入,然后传递个图片出去,看下代码
Observable<Bitmap> observableMap = Observable.just(Environment.getExternalStorageDirectory().getPath() + "/tt.jpg").map(new Function<String, Bitmap>() {
@Override
public Bitmap apply(String s) throws Exception {
File file = new File(s);
if (file.exists()) {
Bitmap bitmap = BitmapFactory.decodeFile(s);
return bitmap;
} else {
return null;
}
}
});
因为在传递的时候就已经做好了处理,所以接收的时候跟接收图片是一样的
observableMap.subscribe(object : Observer<Any> {
override fun onSubscribe(d: Disposable) {
}
override fun onNext(t: Any) {
var bitmap=t as Bitmap
rxImage.setImageBitmap(bitmap)
}
override fun onComplete() {
Log.d(TAG, "onNext:Complete");
}
override fun onError(e: Throwable) {
Log.d(TAG, "onNext:${e.toString()}");
}
})
看下效果,和刚才直接传递是一样的,但是Map有个缺点就是只能一对一传递,如果是多传递,就要用到了FlatMap
看下FlatMap传递的代码Course和Student是两个实体类,没设么特别的意思,便于理解罢了
Student.Course course = new Student.Course("java");
Student.Course course1 = new Student.Course("C#");
Student.Course course2 = new Student.Course(".NET");
Student.Course course3 = new Student.Course("Python");
Student.Course course4 = new Student.Course("PHP");
Student.Course[] courseList = {course, course1, course2, course3, course4};
Student student = new Student("A", courseList);
Observable<Student.Course> observableFlatMap = Observable.fromArray(student).flatMap(new Function<Student, ObservableSource<Student.Course>>() {
@Override
public ObservableSource<Student.Course> apply(Student student) throws Exception {
return Observable.fromArray(student.getmCourseList());
}
});
接收代码跟其他的几乎一样
observableFlatMap.subscribe(object :Observer<Student.Course>{
override fun onSubscribe(d: Disposable) {
}
override fun onNext(t: Student.Course) {
Log.d(TAG, "onNext:${t.courseName}");
}
override fun onComplete() {
Log.d(TAG, "onNext:Complete");
}
override fun onError(e: Throwable) {
Log.d(TAG, "onNext:${e.toString()}");
}
})
效果也达到了预期
RxJava简单使用差不多也就到这里了,如果还想了解更多就只能自己去看源码和去多使用了
DownLoad