一,什么是Rx
1.Rx的基本介绍:Rx是响应式编程的意思,本质是观察者模式,是以观察者(Observer)和订阅者(Subscriber)为基础的异步响应方式。
(1)缩写:ReactiveX时Reactive Extensions的缩写,一般简写为Rx
(2)定义:Rx = Observables + LINQ + Schedulers. LINQ---语言集成查询
(3)突破:ReactiveX不仅仅是一个编程接口,它是一种编程思想的突破,它影响了许多其它的程序库和框架以及编程语言。
(4)Rx库支持.Net,JavaScript,C++,常用有RxJava, RxJS, rx.NET
2.Rx模式以及优点:
<1>使用观察者模式:
(1)创建:Rx可以方便的创建事件流和数据流
(2)组合:Rx使用查询方式的操作符组合和变换数据流
(3)监听:Rx可以订阅任何可观察的数据流并执行操作
<2>简化代码:
(1)函数式风格:对可观察数据流使用无副作用的输入输出函数,避免了程序里错综复杂的状态
(2)简化代码:Rx的操作符通常可以将复杂的难题简化为很少的几行代码
(3)异步错误处理:传统的try/catch没办法处理异常计算,Rx提供了合适的错误处理机制
(4)轻松使用并发:Rx的Observables和Schedulers让开发者可以摆脱底层的线程同步和各种并发问题
3.Rx提供了什么
(1)Rx提供了一些列的操作符,你可以使用它们来过滤(filter)、选择(select)、变换(transform)、结合(combine)和组合(compose)多个Observable,
这些操作符让执行和复合变得非常高效
(2)我们可以把Observable当做Iterable的推送方式的等价物,使用Iterable,消费者从生产者那拉取数据,线程阻塞直至数据准备好。
使用Observable,在数据准备好时,生产者将数据推送给消费者。数据可以同步或异步的到达,这种方式更灵活。
二,初始RxJava:
1.观察者模式面向的需求:A对象(观察者)对B对象(被观察者)的某种变化高度敏感,需要在B变化的一瞬间作出反应(就是A监看B)
2.RxJava的四个基本概念:Observable(被观察者)、Observer(观察者)、subscrible(订阅)、事件。
(1)Observable和Observer通过subscrible()方法实现订阅关系,从而
Observable可以在需要的时候发出事件来通知Observer.
3.RxJava的基本实现:
(1)创建Observer
Observer即观察者,它决定事件触发的时候有怎样的行为。
RxJava中的Observer接口的实现方式。
(2)创建Observable
Observable即被观察者,它决定什么时候触发事件以及触发怎样的事件。
RxJava使用create()方法来创建一个Observable,并为它定义事件触发规则
(3)Subscribe(订阅)
创建了Observable和Observer之后,再创建subscribe()方法将他们联结起来,整条链子就可以工作了
4,使用例子:
第一个例子:自定义接口实现:
(1)创建观察者接口:定义监听的方法
public interface Watcher {
//通过update()方法监听到状态的通知
public void update(String str);
}
(2)创建被观察者接口:提供3个方法,添加观察者,异常观察者,通知提醒所以的观察者
public interface Watched {
//添加观察者
public void addWatcher(Watcher watcher);
//移除观察者
public void removeWatcher(Watcher watcher);
//提醒所以的观察者
public void notifyWatchers(String str);
}
(3)创建实现观察者接口的观察者类:
public class ConcreteWatcher implements Watcher {
@Override
public void update(String str) {
//打印出被观察者的消息的变化
System.out.println(str);
}
}
(4)创建实现被观察者接口的被观察者类:用ArrayList来实现多个观察者对象的监听状况
public class ConcreteWatched implements Watched {
//创建List集合
private List list = new ArrayList<>();
@Override
public void addWatcher(Watcher watcher) {
//添加观察者对象
list.add(watcher);
}
@Override
public void removeWatcher(Watcher watcher) {
//移除观察者对象
list.remove(watcher);
}
@Override
public void notifyWatchers(String str) {
//遍历,通知所有观察者被观察对象的消息变化
for(Watcher watcher : list){
watcher.update(str);
}
}
}
(5)测试类:
public class Test {
public static void main(String[] args)throws Exception{
//新建一个被观察者对象:小明
Watched xiaoming = new ConcreteWatched();
//新建3个观察者来监听小明的状态
Watcher watcher1 = new ConcreteWatcher();
Watcher watcher2 = new ConcreteWatcher();
Watcher watcher3 = new ConcreteWatcher();
//把监听器安装在小明身上
xiaoming.addWatcher(watcher1);
xiaoming.addWatcher(watcher2);
xiaoming.addWatcher(watcher3);
//小明的状改变了
xiaoming.notifyWatchers("我打算要偷东西了");
}
}
输出如下:
我打算要偷东西了
我打算要偷东西了
我打算要偷东西了
第二个例子:利用Observable和Observer这两个类来实现
import java.util.Observable;
import java.util.Observer;
需要配置builde.gradle(app)环境,添加如下两行(这里先把RxAndroid的一起添加了)
compile 'io.reactivex:rxandroid:1.1.0' // RxAndroid
compile 'io.reactivex:rxjava:1.1.0' // 推荐同时加载RxJava
(1)创建SimpleObservable类,继承Observable类:
在里面定义一个数据data,并创建getData()方法,和setData()方法,
再在setData()方法里面设置状态改变监听与通知观察者的方法,如下:
//设置状态改变
setChanged();
//表示状态改变,通知观察者
notifyObservers();
整体代码:
import java.util.Observable;
/**
* Created by maiyu on 2017/6/18.
* 创建一个被观察者类
*/
public class SimpleObservable extends Observable {
//定义一个数据
private int data = 0;
//get方法
public int getData() {
return data;
}
/**
* setData方法
* @param i
*/
public void setData(int i) {
if(this.data != i) {
this.data = i;
//设置状态改变
setChanged();
//表示状态改变,通知观察者
notifyObservers();
}
}
}
(2)创建观察者类:SimpleObserver类,继承Observer:
初始化构造方法(把被观察者作为参数),重写update方法
在update里实现通知,代码如下:
import java.util.Observer;
/**
* Created by maiyu on 2017/6/18.
* 观察者
*/
public class SimpleObserver implements Observer {
/**
* 初始化,为被观察者添加观察者对象
* @param observable
*/
public SimpleObserver(SimpleObservable observable){
observable.addObserver(this);
}
/**
* 当被观察者的数据改变时,触发此方法
* @param o
* @param object
*/
@Override
public void update(Observable o, Object object) {
//强制转换为SimpleObservable类,并执行它的getData()方法
System.out.println("data is changed: " + ((SimpleObservable)o).getData());
}
(3)测试类:
public class Test {
public static void main(String[] args)throws Exception{
//创建被观察者对象
SimpleObservable observable = new SimpleObservable();
//创建观察者对象,把被观察者当做参数
SimpleObserver observer = new SimpleObserver(observable);
observable.setData(1);
observable.setData(2);
//此处,因为状态还是2,没有改变,不会通知
observable.setData(2);
observable.setData(3);
}
}
输出结果:
data is changed: 1
data is changed: 2
data is changed: 3
只有在状态改变时才通知,不改变不通知
在Android编程时,经常会使用后台线程,那么就可以使用这种方式,目前的异步编程方式会导致一些问题,如:
(1).异步任务容易导致内存泄漏
(2)CursorLoaders和ContentProvider的使用经常需要大量的配置数字模板
(3)后台服务长时间运行在后台,不能很快结束操作,会浪费资源
(4)访问网络接口调用返回数据,尤其在使用回调时候,处理数据很麻烦
1.创建观察者
在异步模型中创建观察者:
(1)定义一个方法,它完成某些任务,然后从异步调用中返回一个值,这个方法是观察者的一部分
(2)将这个异步调用本身定义为一个Observable
(3)观察者通过订阅(Subscribe)操作关联到哪个Observable
(4)继续你的业务逻辑,等方法返回时,Observable会发射结果,观察者的方法会开始处理结果或者结果集
2.观察者回调方法:onNext, onError , onComplete
(1)onNext(T item):Observable调用这个方法发射数据,方法的参数就是Observable发射的数据,这个方法可能会被多次调用,取决于我们的实现
(2)onError(Exception ex)
当Observable遇到错误或者无法返回期望的数据时会调用这个方法,这个调用会终止Observable,后续不会再调用onNext和onCompleted,
onError方法的参数就是抛出的异常
(3)onComplete
正常终止,如果没有遇到错误,Observable在最后一次调用onNext之后调用此方法
3.创建操作Create:
(1)使用一个函数从头开始参加一个Observable:
Create{onNext ; onNext ; onComplete}
注意:可在传递给create方法的函数中检查观察者的isUnsubscribed状态,以便在没有观察者的时候,让你的Observable停止发射数据或做昂贵的运算。
4.例子如下:
创建类:RxUtils,用于存放后面没种实现方式的方法
public class RxUtils {
private static final String TAG = RxUtils.class.getSimpleName();
<1>第一例子:使用Observable.create()方法来创建:
(1)创建Observable对象,在create方法里面传入参数new Observable.OnSubscribe()对象,
然后利用onNext设置信息,最后调用onComplete()方法,如下:
//使用Observable.create方法来创建
Observable observable = Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super String> subscriber) {
subscriber.onNext("hello");
subscriber.onNext("good");
subscriber.onNext(downLoadJson());
subscriber.onNext("约吗");
//调用onCompleted()方法来完成
subscriber.onCompleted();
}
});
(2)创建Subscriber对象,重写onError,onComplete,onNext方法:
代码如下:
//创建Subscriber对象,这里传入字符串类型,因为什么我们是发送字符串
Subscriber showsub = new Subscriber() {
@Override
public void onCompleted() {
Log.i(TAG , "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i(TAG , "onError:"+ e.toString());
}
@Override
public void onNext(String s) {
Log.i(TAG , "onNext: " + s);
}
};
/**
* 定义下载方法
* @return
*/
private static String downLoadJson() {
return "json_data";
}
(3)调用Observable对象的subscribe关联Subscriber对象:
/**
* 关联被观察者
*/
observable.subscribe(showsub);
(4)在Activity中为某个按钮设置监听:
public void btnOnClick(View view){
RxUtils.createObservable();
}
(5)输出结果如下:
06-20 01:30:46.313 6162-6162/? I/RxUtils: onNext: hello
06-20 01:30:46.313 6162-6162/? I/RxUtils: onNext: good
06-20 01:30:46.313 6162-6162/? I/RxUtils: onNext: json_data
06-20 01:30:46.313 6162-6162/? I/RxUtils: onNext: 约吗
06-20 01:30:46.313 6162-6162/? I/RxUtils: onCompleted
<2>第二种方法:也是利用create方法,只是不用创建Observable和Subscriber对象,而是直接实现,如下:打印整数1到10
public static void createObservable2(){
Observable.create(new Observable.OnSubscribe() {
@Override
public void call(Subscriber super Integer> subscriber) {
//如果没有解除关联
if(!subscriber.isUnsubscribed()){
for(int i = 0 ; i < 10 ; i++){
subscriber.onNext(i);
}
subscriber.onCompleted();
}
}
}).subscribe(new Subscriber() {
@Override
public void onCompleted() {
Log.i(TAG , "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i(TAG , "e: " + e.toString());
}
@Override
public void onNext(Integer integer) {
Log.i(TAG , "onNext: " +integer);
}
});
}
Activity中按钮监听:
public void btnOnClick2(View view){
RxUtils.createObservable2();
}
输出结果:
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 0
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 1
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 2
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 3
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 4
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 5
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 6
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 7
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 8
06-20 01:36:37.593 6162-6162/? I/RxUtils: onNext: 9
06-20 01:36:37.593 6162-6162/? I/RxUtils: onCompleted
<3>第3种方法:from()方法,定义数组
/**
* Observable.from()方法
* 使用在被观察者,返回的一般都是数据类型
*/
public static void from(){
Integer[] items = {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9};
Observable observable = Observable.from(items);
observable.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.i(TAG , o.toString());
}
});
}
输出:
06-20 02:01:43.081 6162-6162/? I/RxUtils: 1
06-20 02:01:43.081 6162-6162/? I/RxUtils: 2
06-20 02:01:43.081 6162-6162/? I/RxUtils: 3
06-20 02:01:43.081 6162-6162/? I/RxUtils: 4
06-20 02:01:43.081 6162-6162/? I/RxUtils: 5
06-20 02:01:43.081 6162-6162/? I/RxUtils: 6
06-20 02:01:43.081 6162-6162/? I/RxUtils: 7
06-20 02:01:43.081 6162-6162/? I/RxUtils: 8
06-20 02:01:43.081 6162-6162/? I/RxUtils: 9
--------- beginning of /dev/log/system
<4>第4种:Interval指定时间间隔发送数据:
/**
* interval指定某一时刻进行数据发送:定时器
*/
public static void interval(){
//每隔1秒发送一次数据
Observable observable = Observable.interval(1 , 1 , TimeUnit.SECONDS);
observable.subscribe(new Action1() {
@Override
public void call(Object o) {
Log.i(TAG , o.toString());
}
});
}
06-20 02:04:28.997 25326-25438/? I/RxUtils: 0
06-20 02:04:29.997 25326-25438/? I/RxUtils: 1
06-20 02:04:30.997 25326-25438/? I/RxUtils: 2
06-20 02:04:32.001 25326-25438/? I/RxUtils: 3
06-20 02:04:32.997 25326-25438/? I/RxUtils: 4
...
<5>第5种:just来实现范围数据,参数为多个数组对象,如:
/**
* 范围数据:如下面依次输出两个数组的元素
*/
public static void just(){
//定义两个数组
Integer[] items1 = {1 , 3 , 5 , 7 , 9};
Integer[] items2 = {2 , 4 , 6 , 8 , 10};
//调用Observable.just(数组1,数组2,.....数组10);
Observable observable = Observable.just(items1 , items2);
//在这里设置Subscriber的类型为Integer[]:对应上面的Integer类型的数组
observable.subscribe(new Subscriber() {
@Override
public void onCompleted() {
Log.i(TAG , "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i(TAG , "onError: " + e.getMessage());
}
@Override
public void onNext(Integer[] o) {
for(Integer i : o)
Log.d(TAG , "onNext : " +i);
}
});
}
输出结果:依次输出两个数组的数据
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 1
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 3
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 5
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 7
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 9
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 2
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 4
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 6
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 8
06-20 02:07:00.337 25643-25643/? D/RxUtils: onNext : 10
06-20 02:07:00.337 25643-25643/? I/RxUtils: onCompleted
<6>第6种:利用range来实现从指定初始位置和个数的范围,如:
/**
* range方法:定义开始下标与个数
*/
public static void range(){
//利用Observable.range(开始下标,个数);
Observable observable = Observable.range(3 , 5);
//传入Action1的参数类型Integer
observable.subscribe(new Action1() {
@Override
public void call(Integer integer) {
Log.d(TAG , "call : " + integer);
}
});
}
输出结果:
06-20 02:08:38.109 25643-25643/? D/RxUtils: call : 3
06-20 02:08:38.109 25643-25643/? D/RxUtils: call : 4
06-20 02:08:38.109 25643-25643/? D/RxUtils: call : 5
06-20 02:08:38.109 25643-25643/? D/RxUtils: call : 6
06-20 02:08:38.109 25643-25643/? D/RxUtils: call : 7
--------- beginning of /dev/log/system
<7>第7种:利用filter来实现某些过滤信息:
/**
* Observable.filter()方法:用于过滤某些东东
*/
public static void filter(){
//创建一个数组
Integer[] items = {1 , 2 , 3 , 4 , 5 , 6};
//调用from添加
Observable observable = Observable.from(items);
//添加过滤器,传入参数:过滤小于等于3的数字
observable.filter(new Func1() {
@Override
public Boolean call(Integer integer) {
return integer > 3;
}
})
//设置订阅者是如何执行的:Schedulers.io---通过网络获取数据
.observeOn(Schedulers.io())
.subscribe(new Subscriber() {
@Override
public void onCompleted() {
Log.d(TAG , "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.d(TAG , "onError : " + e.getMessage());
}
@Override
public void onNext(Integer integer) {
Log.d(TAG , "onNext : " + integer);
}
});
}
结果如下:
06-20 02:13:52.561 26628-26661/? D/RxUtils: onNext : 4
06-20 02:13:52.561 26628-26661/? D/RxUtils: onNext : 5
06-20 02:13:52.561 26628-26661/? D/RxUtils: onNext : 6
06-20 02:13:52.561 26628-26661/? D/RxUtils: onCompleted
1.替代AsyncTask完成下载操作
2.结合OkHttp完成网络访问操作、包括下载文件、提交form表单数据
3.结合ListView、GridView使用完成对图文混排操作
4.结合OkHttp网络访问框架使用
5.RxAndroid编程思路的总结
1.替代AsyncTask完成下载操作:如下载一直图片
(1)在Activity中:
* 在实际开发中Activity充当的角色太多了:
* 1.UI主线程负责绘制UI
* 2.开启子线程获取网络数据
* 3.赋值到控件中
* 4.判断逻辑等等
/**
* 下载张图片:
* 1.AsyncTask
* 2.Handler机制
* 3.发现有更好的即观察者模式
*/
如第1种:那么必须创建类继承AsyncTask或者自己封装:
public class DownLoadUtils {
/**
* 传统模式,
*
* @param path
* @return
*/
public static byte[] downloadImg(String path, CallBack callBack) {
//在这里定义异步任务
return null;
}
interface CallBack {
void callback(byte[] data);
}
}
(2)创建工具类:
主要有如下几个知识点:
------定义并在构造方法里创建OkHttpClient
记得在build.gradle添加OkhttpClient的依赖
compile 'com.squareup.okhttp:okhttp:2.7.2'
------使用Observable创建下载方法,参数为path,
public class DownLoadUtils {
//定义OkHttpClient
private OkHttpClient okHttpClient ;
/**
* 构造函数:实例化OkHttpClient对象
*/
public DownLoadUtils(){
okHttpClient = new OkHttpClient();
}
/**
* 创建观察者模式的下载方法,这里
* @param path -----传入地址参数
* @return ------返回btye[]数组
*/
public Observable downloadImg(final String path){
//使用create()方法
return Observable.create(new Observable.OnSubscribe() {
@Override
public void call(final Subscriber super byte[]> subscriber) {
//判断是否已经绑定订阅
if(!subscriber.isUnsubscribed()){
//使用OkhttpClient访问网络步骤
//创建Request对象,调用.url()传入地址,build()完成
Request request = new Request.Builder().url(path).build();
//调用okttpClient.newCall(Request对象).enqueue()执行异步get请求
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
//执行subscriber.onError()方法
subscriber.onError(e);
}
/**
* 请求成功
* @param response
* @throws IOException
*/
@Override
public void onResponse(Response response) throws IOException {
//判断返回结果是否成功
if(response.isSuccessful()){
//获取返回的byte[]数组
byte[] data = response.body().bytes();
//判空
if(data != null){
//发射数据
subscriber.onNext(data);
}
}
//完成
subscriber.onCompleted();
}
});
}
}
});
}
}
在Activity中:
初始化DownLoad类:
utils = new DownLoadUtils();
为按钮设置监听,在监听里面执行代码如下:
//下载图片------设置订阅执行方式(通过网络获取数据)-----设置主线程显示
utils.downloadImg(imgPath).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber() {
@Override
public void onCompleted() {
Log.i(TAG , "onCompleted");//对话框取消
}
@Override
public void onError(Throwable e) {
Log.i(TAG , "onError: " + e);
}
@Override
public void onNext(byte[] bytes) {
//显示图片,这里没有对图片进行压缩等处理
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes , 0 , bytes.length);
mImg.setImageBitmap(bitmap);
}
});
如传入地址:
private String imgPath = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1497953788142&di=370d893f7390ea12dc770083b171c1f2&imgtype=0&src=http%3A%2F%2Fxke8.com%2Fuploads%2Fallimg%2Fc150921%2F1442O51G4A0-1I13.jpg";
有点长,不过结果辣眼睛,瞬间秒杀你的困意:
主要代码如下:
工具类:
/**
* Created by maiyu on 2017/6/20.
* 登录类
*/
public class LoginUtils {
//定义OkHttpClent对象
private OkHttpClient okHttpClient ;
public LoginUtils(){
okHttpClient = new OkHttpClient();
}
/**
* 登录实现
* @param url
* @param params
* @return String
*/
public Observable login(final String url , final Map params){
return Observable.create(new Observable.OnSubscribe() {
@Override
public void call(final Subscriber super String> subscriber) {
//判断是否已经绑定
if(!subscriber.isUnsubscribed()){
//创建FormEncodingBuilder对象
FormEncodingBuilder builder = new FormEncodingBuilder();
//添加参数
if(params != null && !params.isEmpty()){
for(Map.Entry entry : params.entrySet()){
builder.add(entry.getKey() , entry.getValue());
}
}
//创建RequestBody对象
RequestBody body = builder.build();
//创建Request对象
Request request = new Request.Builder().url(url).post(body).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
subscriber.onError(e);
}
@Override
public void onResponse(Response response) throws IOException {
if(response.isSuccessful()){
//订阅
subscriber.onNext(response.body().string());
}
subscriber.onCompleted();
}
});
}
}
});
}
}
登录按钮监听实现:
public void toLogin(){
Map params = new HashMap();
params.put("username" , "获取用户名");
params.put("password" , "获取密码");
loginUtils.login(loginUrl , params).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber() {
@Override
public void onCompleted() {
Log.i(TAG , "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i(TAG , "onError : " + e);
}
@Override
public void onNext(String s) {
//跳转...
Intent intent = new Intent();
startActivity(intent);
}
});
}