遇到新的知识我通常从三个方面去快速学习(what - 是什么 why - 为什么用它,它解决了什么样的问题 how - 如何使用),接下来我就从这三个方面来分析.
- 1.what?
- RxJava 到底是什么?让我们直接跳过官方那种晦涩的追求精确的定义,其实初学RxJava只要把握两点:
- 观察者模式 和 异步,就基本可以熟练使用RxJava了。异步 在这里并不需要做太多的解释,因为在概念和使用上,并没有太多高深的东西。大概就是你脑子里想能到的那些多线程,线程切换这些东西。我会在后面会讲解它的用法。说到根上,它就是一个实现异步操作的库.
- 我们先把 观察者模式 说清楚 “按下开关,台灯灯亮”
在这个事件中,台灯作为观察者,开关作为被观察者,台灯透过电线来观察开关的状态来并做出相应的处理
- 开关(被观察者)作为事件的产生方(生产“开”和“关”这两个事件),是主动的,是整个开灯事理流程的起点。
- 台灯(观察者)作为事件的处理方(处理“灯亮”和“灯灭”这两个事件),是被动的,是整个开灯事件流程的终点。
- 在起点和终点之间,即事件传递的过程中是可以被加工,过滤,转换,合并等等方式处理的。
- 2.why?
- 简洁,并不是指代码量上的那种简洁,而是逻辑上的简洁,随着程序逻辑变得越来越复杂,它依然能够保持简洁。
- 3.how?
- RxJava也是基于观察者模式来组建自己的程序逻辑的,就是构建被观察者(Observable),观察者(Observer/Subscriber),然后建立二者的订阅关系(就像那根电线,连接起台灯和开关)实现观察,在事件传递过程中还可以对事件做各种处理。
- 上用法
- 简单使用
private void helloWorldSimple() {
//创建消费者,消费者接受string类型的字符串
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d(TAG, "accept " + s);
}
};
//被观察者发出Hello World, 并且指定该事件的消费者为consumer
//从代码上看是 被观察者订阅了观察者(consumer),为什么是这样的呢?在我们看来应该是consumer订阅了被观察者,,,
//之所以这样写是为了保证 流式API调用风格(我理解是链式编程,如下)
//由于被观察者产生事件,是事件的起点,那么开头就是用Observable这个主体调用来创建被观察者,产生事件,为了
// 保证流式API调用规则,就直接让Observable作为唯一的调用主体,一路调用下去。
Observable.just("hello world").subscribe(consumer);
}
- 升级使用
private void helloWorldComplex() {
//observer 可以看出完整版的comsumer
Observer<String> observer = new Observer<String>() {
//当Observable调用subscribe方法时会回调该方法
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe ");
}
@Override
public void onNext(String value) {
Log.d(TAG, "onNext " + value);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError ");
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete ");
}
};
Observable.just("hello world").subscribe(observer);
}
- 进阶使用
private void helloWorldHard() {
//创建一个观察者
Observer<String> observer = new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe ");
}
@Override
public void onNext(String value) {
Log.d(TAG, "onNext " + value);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError ");
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete ");
}
};
//创建一个被观察者
Observable<String> observable = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext("hello world"); //调用观察者的onnext方法
e.onComplete();
}
});
observable.subscribe(observer);
}
- 下面介绍一下RxJava的操作符
- 变换 map 操作符
private void mapDemo() {
//将路径字符串转换为图片
String imagUrl = "http://192.168.18.45:8080/GooglePlayServer/image?name=app/com.renren.mobile.android/screen0.jpg";
Observable.just(imagUrl)
.subscribeOn(Schedulers.newThread()) //指定了被观察者执行的线程环境,在子线程中执行网络请求
.map(new Function<String, Bitmap>() {
@Override
public Bitmap apply(String s) throws Exception {
return createBitmap(s);
}
})
.observeOn(AndroidSchedulers.mainThread()) //切换到主线程中执行onNext() 更新ui
.subscribe(new Observer<Bitmap>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Bitmap value) {
Log.d(TAG, "onNext ");
//显示图片
mImage.setImageBitmap(value);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete ");
}
});
}
/**
* 通该方法得到bitmap对象
* 网络请求属于耗时操作,需要在子线程中进行 RxJava再代码中完成线程调度
*
* @param s imagurl
* @return Bitmap
*/
private Bitmap createBitmap(String s) {
try {
URL url = new URL(s);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
if (connection.getResponseCode() == 200) {
InputStream inputStream = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
- 筛选 filter 操作符
private void filterDemo() {
//Consumer可以看成精简版的observer
Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.d(TAG, "accept " + s); //这里观察者接收到包子
}
};
Observable.just("包子", "馒头", "稀饭")
.filter(new Predicate<String>() {
@Override
public boolean test(String s) throws Exception {
return s.equals("包子"); //只允许包子通过测试
}
})
.subscribe(consumer);
}
- flatmap 能够链式地完成数据类型的转换和加工
private void flatmapDemo() {
//遍历学校中每个班级的每个同学,按照以前方式
// for (int i = 0; i < 3; i++) {
// for (int j = 0; j < 3; j++) {
// for (int k = 0; k < 3; k++) {
// 伪代码
// }
// }
// }
//这样的代码可读性很差,数据越复杂越难读
//遍历学校中每个班级的所有组中的所有学生
//使用这种方式不管有多少层,代码的阅读性不会变得复杂
Observable.fromIterable(new School().mClasses)
.flatMap(new Function<Class, ObservableSource<Group>>() {
@Override
public ObservableSource<Group> apply(Class aClass) throws Exception {
Log.d(TAG, "apply " + aClass.toString());
return Observable.fromIterable(aClass.group);
}
})
.flatMap(new Function<Group, ObservableSource<Student>>() {
@Override
public ObservableSource<Student> apply(Group group) throws Exception {
Log.d(TAG, "apply " + group.toString());
return Observable.fromIterable(group.mStudents);
}
}).subscribe(new Observer<Student>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Student value) {
Log.d(TAG, "onNext " + value.toString());
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}