使用RxJava可以方便实现观察者模式,数据转换和线程之间通信
https://github.com/ReactiveX/RxJava
在Android中使用RxAndroid增加安卓主线程支持:
https://github.com/ReactiveX/RxAndroid
实际开发中在gradle中注册对应的依赖即可:
compile 'io.reactivex:rxandroid:1.1.0'
观察者模式一般要有两个对象:
1.被观察者:Obserable
2.观察者:Observer
观察者和被观察者绑定后,被观察者在某种事件发生时会向所有观察它的观察者发送事件,即调用观察者的回调函数。
使用java.util里的观察者应该是这样的:
import android.util.Log;
import java.util.Observable;
import java.util.Observer;
public class ObserverTest {
void test0() {
//创建被观察者
DemoObserable obserable = new DemoObserable();
//创建一个观察者
Observer observer1 = new Observer() {
//观察者接收到事件时的操作
@Override
public void update(Observable observable, Object data) {
Log.e("TAG", "ToObserver1: " + data);
}
};
//添加绑定
obserable.addObserver(observer1);
//被观察者发送事件
obserable.subscribe("Hello World!!");
//被观察者将观察者移除
obserable.deleteObserver(observer1);
}
//被监听者
public class DemoObserable extends Observable {
//被监听者发送数据给所有观察者
void subscribe(String data) {
setChanged();
notifyObservers(data);
}
}
}
假设观察者有多个,可以依次注册,删除:
//创建被观察者
DemoObserable obserable = new DemoObserable();
//创建一个观察者
Observer observer1 = new Observer() {
//观察者接收到事件时的操作
@Override
public void update(Observable observable, Object data) {
Log.e("TAG", "ToObserver1: " + data);
}
};
//创建一个观察者
Observer observer2 = new Observer() {
//观察者接收到事件时的操作
@Override
public void update(Observable observable, Object data) {
Log.e("TAG", "ToObserver2: " + data);
}
};
//添加绑定
obserable.addObserver(observer1);
obserable.addObserver(observer2);
然而,我们接下来使用 rx.Observer, rx.Observable, 思想也是类似的:
1.观察者与被观察者
void test0() {
Observable.OnSubscribe<String> onSubscribe = new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("hello world!!");
subscriber.onCompleted();
}
};
Observable<String> observable = Observable.create(onSubscribe);
Observer<String> observer = new Observer<String>() {
@Override
public void onNext(String s) {
Log.e("TAG", s);
}
@Override
public void onCompleted() {
Log.e("TAG", "completed");
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "error" + e);
}
};
observable.subscribe(observer);
}
完成了类似的功能。
Observable构造方法是保护的,只能通过提供的静态方法创建对象,如Observable.create()
RxJava可以使用链式调用简化代码,所以也可以写成:
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("hello world!!");
subscriber.onCompleted();
}
}).subscribe(new Observer<String>() {
@Override
public void onNext(String s) {
Log.e("TAG", s);
}
@Override
public void onCompleted() {
Log.e("TAG", "completed");
}
@Override
public void onError(Throwable e) {
Log.e("TAG", "error" + e);
}
});
如果直接知道被监听者发送事件onNext()时的参数,可以使用just()来创建Observable,效果和上例一样
Observable.just("Hello World!")
.subscribe(new Observer<String>() {
@Override
public void onCompleted() {
Log.e("TAG", "complete");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
Log.e("TAG", s);
}
});
just函数可以传入多个参数,事件依次调用后最后执行onComplete()
Observable.just("Hello World!", "RxJava Demo")
.subscribe(new Observer<String>() {
@Override
public void onCompleted() {
Log.e("TAG", "complete");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
Log.e("TAG", s);
}
});
如果观察者只需要重写onNext()方法,可以直接用ActionX来节省掉onError和onComplete的代码:
Observable.just("Hello World!", "RxJava Demo")
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("TAG", s);
}
});
现在观察者也变的好简单,使用多个参数just()来创建也可以用from(T[])来创建,与上例等价:
String[] arr = {"Hello World!", "RxJava Demo"};
Observable.from(arr)
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("TAG", s);
}
});
如果不想用Observer,又想处理onError和onComplete,就需要在subscribe()函数传多个ActionX:
String[] arr = {"Hello World!", "RxJava Demo"};
Action1 nextAction, errorAction;
Action0 completeAction;
nextAction = new Action1<String>() {
@Override
public void call(String s) {
Log.e("TAG", s);
}
};
errorAction = new Action1<Exception>() {
@Override
public void call(Exception e) {
e.printStackTrace();
}
};
completeAction = new Action0() {
@Override
public void call() {
Log.e("TAG", "complete");
}
};
Observable.from(arr)
.subscribe(nextAction, errorAction, completeAction);
2.观察者与被观察者在不同线程
加上线程控制语句subscribeOn,observeOn,就可以将被观察者和观察者指定在不同线程中:
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
Log.e("TAG", "I am in computation");
subscriber.onNext("Hello World!!");
}
})
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("TAG", s);
}
});
两个操作发生在不同线程中,通过log可以看出来:
03-29 21:00:39.333 13153-13226/com.hzy.rxjavademo E/TAG: I am in computation
03-29 21:00:39.334 13153-13153/com.hzy.rxjavademo E/TAG: Hello World!!
03-29 21:00:39.914 13153-13227/com.hzy.rxjavademo E/TAG: I am in computation
03-29 21:00:39.915 13153-13153/com.hzy.rxjavademo E/TAG: Hello World!!
03-29 21:00:40.607 13153-13228/com.hzy.rxjavademo E/TAG: I am in computation
03-29 21:00:40.608 13153-13153/com.hzy.rxjavademo E/TAG: Hello World!!
通过日志pid可以看到,Observable执行会开启新的线程,而Observer观察者收到消息后执行的操作在UI线程执行,所以可以方便的替代之前Android的new Thread加Handler发送消息的机制。
如下代码就可以完成一个完整的异步网络请求,并把结果和出错信息通知到UI线程的观察者:
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
try {
URL url = new URL("https://m.baidu.com/");
InputStream is = url.openStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
StringBuilder builder = new StringBuilder();
while ((line = br.readLine()) != null) {
builder.append(line);
}
subscriber.onNext(builder.toString());
} catch (Exception e) {
subscriber.onError(e);
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("TAG", s);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
throwable.printStackTrace();
}
});
异步操作变得好简单,而且很容易理解
3.数据的过滤
数据过滤使用filter方法:
String[] arr = {"Hello World!", "RxJava Demo", "RxAndroid"};
Observable.from(arr)
.filter(new Func1<String, Boolean>() {
@Override
public Boolean call(String s) {
return s.startsWith("Rx");
}
})
.subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("TAG", s);
}
});
这时,如例子中所有返回以Rx开头字符串的事件,才会去通知观察者。
4.数据的转换
消息发送者返回的数据用map()进行转化后再发送给观察者
Observable.just(123)
.map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
String ret = integer + ":" + integer * 2;
return ret;
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("TAG", s);
}
});
把消息发送者发来的 Integer类型转成String类型再传给观察者去处理。
使用lift()把一个观察者转成另一个:
Observable.just(123)
.lift(new Observable.Operator<String, Integer>() {
@Override
public Subscriber<? super Integer> call(final Subscriber<? super String> subscriber) {
return new Subscriber<Integer>() {
@Override
public void onCompleted() {
subscriber.onCompleted();
}
@Override
public void onError(Throwable e) {
subscriber.onError(e);
}
@Override
public void onNext(Integer integer) {
subscriber.onNext("hello" + integer);
}
};
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("TAG", s);
}
});
把一个Integer类型的Subscriber转成String类型,Subscriber实现Observer接口,所以
Subscriber也是观察者。
使用compose直接把被监听者转换掉,Transformer规定了转换的规则,Obserable怎么转换呢,还是用个map来转吧,Transformer在此显得多此一举了:
Observable.just(123)
.compose(new Observable.Transformer<Integer, String>() {
@Override
public Observable<String> call(Observable<Integer> integerObservable) {
return integerObservable.map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
return integer + "hello";
}
});
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.e("TAG", s);
}
});
把Integer类型转换成String类型
5.条件判断
条件判断的Observable范型都会被转换成Boolean类型
判断是否存在某种类型用exists()函数
Observable.just(123, 20, 34, 4, 0, 2)
.exists(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
return integer == 0;
}
})
.subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean aBoolean) {
Log.e("TAG", "" + aBoolean);
}
});
判断那些值中是否存在为0的Integer,显然存在,返回true
用all()判断是否全都是某种情况:
Observable.just(123, 20, 34, 4, 0, 2)
.all(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
return integer > 0;
}
})
.subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean aBoolean) {
Log.e("TAG", "" + aBoolean);
}
});
上面那些值全都大于0么,显然不是,返回false。
6.观察者嵌套
有一种场景,观察者收到消息后,不能完全处理掉消息,自身又作为消息发送者给其他观察者发消息。
Observable.just(123)
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Observable.just(integer)
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.e("TAG", "" + integer);
}
});
}
});
两层嵌套之后缩进已经很长了,为解决这个问题,可以用flatMap()来减少缩进:
Observable.just(123)
.flatMap(new Func1<Integer, Observable<Integer>>() {
@Override
public Observable<Integer> call(Integer integer) {
return Observable.just(integer);
}
}).subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
Log.e("TAG", "" + integer);
}
});
这样,缩进好多了。
最后是一个综合实例:
//使用IO线程读取SD卡上所有png文件并在主线程上打印
private void testy() {
Observable.create(new Observable.OnSubscribe<File>() {
@Override
public void call(Subscriber<? super File> subscriber) {
//获取外部存储上的所有文件
File exDir = Environment.getExternalStorageDirectory();
traceFiles(exDir, subscriber);
}
}).subscribeOn(Schedulers.io())
//过滤出png文件
.filter(new Func1<File, Boolean>() {
@Override
public Boolean call(File file) {
return file.isFile() && file.getName().endsWith(".png");
}
//使用buffer防止消息发送过快
}).onBackpressureBuffer()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<File>() {
@Override
public void call(File file) {
Log.e("TAG", file.getAbsolutePath());
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
Log.e("TAG", "Error:" + throwable);
throwable.printStackTrace();
}
});
}
private void traceFiles(File file, Subscriber<? super File> subscriber) {
subscriber.onNext(file);
if (file.isDirectory()) {
for (File f : file.listFiles()) {
traceFiles(f, subscriber);
}
}
}
结束
分享到:
相关推荐
RxJava与RxAndroid通常结合使用,开发者可以利用RxJava的响应式特性,在Android应用中处理复杂的数据流和异步任务,使得代码更加简洁易读,并且提升应用的性能和响应速度。同时,通过利用RxAndroid提供的特定于...
通过研究和理解这些代码,开发者不仅可以学习如何实现Markdown解析,还能深入了解如何在Android应用中有效地使用RxJava。这对于提升Android开发技能,尤其是处理文本和事件流的处理,有着极大的帮助。
读书笔记:Android中的响应式编程RxJavaRxAndroid
在Android开发领域,掌握全面的知识点对于从培训到工作至关重要。这份"android 非常全培训笔记"无疑是为开发者提供了一个宝贵的参考...建议读者结合笔记中的实例逐步学习,不断练习,从而在Android开发之路上越走越远。
在移动设备上,笔记应用是不可或缺的一部分,而“Android--极简笔记App”正是这样一个基于Material Design设计规范的轻量级应用程序。这款应用利用了Android平台上的先进技术和最佳实践,如RxAndroid、MVP(Model-...
8. **权限管理**:Android 6.0(API级别23)以后的动态权限申请,理解运行时权限模型,以及在代码中如何处理权限请求。 9. **通知与服务**:创建和管理通知,使用Foreground Service确保服务在后台持续运行,以及...
13. **多线程和异步处理**:Android中的UI线程不能执行耗时操作,因此需要使用线程池、AsyncTask、Handler或第三方库如RxJava来处理后台任务。 14. **动画(Animation)**:Android支持属性动画、帧动画和视图动画,...
新版Android开发教程及笔记将涵盖Android系统的基本架构、应用程序生命周期管理以及UI设计等核心概念。 1. **Android系统架构**:Android系统分为应用层、应用框架层、系统运行库层和Linux内核层。开发者主要在应用...
Android学习入门笔记主要涵盖了一系列关于Android开发的基础知识,旨在帮助初学者快速掌握这一全球最流行的移动操作系统...通过阅读“Android学习入门笔记”中的学习课件,你应该能逐步建立起对Android开发的全面认知。
10. **第三方库集成**:许多第三方库如Retrofit、Dagger、RxJava等,大大简化了Android开发,笔记会讲解如何选择并正确地集成这些库。 11. **单元测试与自动化测试**:理解JUnit、Espresso等工具,进行应用的功能...
Rxjava操作符,中文文档,使用案例,方便随时查阅学习. 安卓艺术开发探索读书笔记,EffectiveJava读书笔记. 收集各大神博客以及安卓笔记,安卓面试笔记等方便手机端查看. 更新说明 v2.2.2 1.增加了一些最近在学习比较好...
综上所述,这个开源项目展示了如何在Android应用中应用Material Design,使用MVP、Dagger2和RxJava等现代开发工具和框架,以及如何解决大型应用的Dex管理和加载问题,为开发者提供了学习和借鉴的价值。通过研究和...
3. **Android笔记应用的基本结构** - **MainActivity**: 应用的主要入口,通常负责初始化界面和处理用户交互。 - **NoteActivity/EditorActivity**: 用于创建和编辑笔记的活动,可能包括输入框、编辑器和保存功能...
在IT行业中,RxJava是一个非常重要的库,尤其在Android开发中被广泛应用。它是一个响应式编程库,允许开发者以一种声明式的方式处理异步数据流。这个“rxjava学习代码”压缩包提供了一种深入理解RxJava 2.x版本的...
在Android开发领域,掌握核心...以上只是Android开发中的冰山一角,这份"Android笔记"可能会涵盖更多细节和实战案例,是学习和进阶Android开发的宝贵资料。通过深入学习和实践,你可以成为一名出色的Android开发者。
这个压缩包中的"Android开发教程&笔记"很可能包含了关于这些主题的详细资料,对于初学者或者经验丰富的开发者来说,都是宝贵的资源。 1. **Android基础知识**:Android是Google主导的开源移动操作系统,它基于Linux...
3. **Activity与Intent**:Activity是Android应用中的一个独立屏幕,Intent则用来在不同的Activity之间进行通信。理解Activity的生命周期和Intent的工作原理对于创建交互式应用至关重要。 4. **Fragment**:...
《Android进阶笔记》是针对Android开发者的一份详尽学习资料,主要涵盖了各种技术框架、博客社区和推荐书籍,旨在帮助开发者深入理解Android系统并提升专业技能。这份资源的开源特性意味着开发者可以自由访问和分享...
以下将详细解析笔记中可能涉及的关键知识点。 1. **Android系统架构**:Android系统由Linux内核、运行库层、应用程序框架层以及应用程序层构成。理解这四层架构对开发者至关重要,它帮助我们了解系统如何工作,以及...