Rxjava的使用

Rxjava是一个异步框架,它是基于观察者模式(简单来说,就是观察者监视被观察者,当被观察者进行动作的时候,被观察者做出反应)。其主要优点在于结构化,使用它可以使你的代码更加简洁。
首先导包,我是用了Retrofit里的Rxjava

compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'

也可以导专门做Rxjava的包

compile 'io.reactivex:rxjava:1.0.14'
compile 'io.reactivex:rxandroid:1.0.1'
  • 一个简单例子
public void testrxjava(){
        //创建观察者
        Observer<String> observer=new Observer<String>() {
            //被观察者完成后回调
            @Override
            public void onCompleted() {
                Log.d("completed","完成");
            }
            //出错时回调
            @Override
            public void onError(Throwable e) {
            }
            //进行时回调
            @Override
            public void onNext(String s) {
                Log.d("onNext",s);
            }
        };
        //创建被观察者
        Observable observable=Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                subscriber.onNext("步骤1");
                subscriber.onNext("步骤2");
                subscriber.onCompleted();
            }
        });
        //通过订阅来绑定观察者与被观察者
        observable.subscribe(observer);
    }

上面的代码就是一个最简单的Rxjava,但是并没有什么用,它一般是写成匿名类的方式,博文后面也都是采用匿名类的方式来写代码的。再介绍一个类Subscriber,它与Observer用法一样,只不过除了上述三个方法还多了个可重写的方法onStart(在观察者刚开始,事件还没有传递时调用,用于做一些准备工作),后面有些地方用的是这个类。

  • 创建、重做、重试.
    先说说创建
    1、form方式创建,传入一个集合,Observer会把集合的item一个个读出来
 Observable.from(new String[]{"123","abc"}).subscribe(new Observer<String>() {
            @Override
            public void onCompleted() {
            }

            @Override
            public void onError(Throwable e) {
            }

            @Override
            public void onNext(String s) {
                Log.d("onNext",s);
            }
        });

2、just方式创建,just里面可以传多个对象进去,所传对象不是同一种对象是用Serializable对象来处理数据。

Observable.just("3",3).subscribe(new Subscriber<Serializable>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Serializable serializable) {
                Log.d("onNext",serializable.toString());
            }
        });

3、create创建,如上述的简单例子,直接创建一个被观察者对象
4、interval创建,创建一个指定时间间隔发送序列号的对象,可用于倒计时。

//每毫秒进行一次操作
        Observable<Long> observable=Observable.interval(1, TimeUnit.MILLISECONDS);
        observable.subscribe(new Subscriber<Long>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Long aLong) {
                Log.d("onNext",aLong.toString());
                if(aLong>=2000) this.unsubscribe();
            }
        });

还有:timer创建,延迟指定时间发送一条数据(固定为 0);
rang创建,发送一定范围类连续整数
empty创建,不发送任务数据,直接回调oncompleted
error创建,不发送任务数据,直接回调onerror
never创建,什么也不发送,什么也不回调
defer创建,每次订阅的时候创建一个对象。
重做:
repeat,observable重复发送onnext数据通知,次数达到后才发送oncompleted通知

Observable<Long> observable=Observable.interval(1, TimeUnit.MILLISECONDS);
        observable.repeat();//重做无限次
        observable.repeat(3);//重做三次

repeatwhen,在发送一个onnext通知后,根据条件确定是否重复发送。
重试:
retry,在observable出现异常是不发送onerror通知而是,重新订阅observable,直到不出现异常或者重试次数达上限,用法与repeat类似。
retryWhen,有条件的重试。

  • Action和Func
    对于之前的observer,都必须重写三个函数,有时我们并不需要重写三个函数,这个时候就得用到action了。action可以看成是一个只有一个方法的observer,它分为action0和actionX(x为几则表示有几个参数),action0没有参数,action1只有一个参数,而且订阅的时候可以绑定多个action(限定第一个位置只能具备泛型的actionX,第二个位置只能Throwable类型的actionX,第三个action0),这样,我们使用起来就很自由了。一般情况只用第一个位置就行了。
Action1<String> action1=new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d("action1",s);
            }
        };
        Action1<Throwable> action2=new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                throwable.printStackTrace();
            }
        };
        Action0 action0=new Action0() {
            @Override
            public void call() {
            }
        };
        Observable.just("3","3").subscribe(action1,action2,action0);
    }

func与action只有一点区别,func有返回值,常用与转换,action没有返回值。

  • 转换、过滤、合并
    转换:
    map,将一种类型转换成另一种类型后再发送,而且可以多次调用这个方法,进行多次转换。
Observable.just("abcd","123").map(new Func1<String, Integer>() {

            @Override
            public Integer call(String s) {
                return s.length();
            }
        }).subscribe(new Action1<Integer>() {
            @Override
            public void call(Integer integer) {
                Log.d("call",String.valueOf(integer));
            }
        });

flatmap,这个转换的返回值是一个observable,也就是把开始那个observable发送的数据,我自己拿到再以我自己的方式发送。下面这个例子,用flat的目的是,避免observer中使用for嵌套。但是,flatmap是对之前那个observer发送来的数据做合并,而且是交错的,也就是不能保证顺序。

ArrayList<String> s=new ArrayList<String>();
        s.add("a");
        s.add("b");
        s.add("c");
        Observable.just(s).flatMap(new Func1<ArrayList<String>, Observable<?>>() {
            @Override
            public Observable<?> call(ArrayList<String> strings) {
                Observable<String> obs=Observable.from(strings);
                return obs;
            }
        }).subscribe(new Action1<Object>() {
            @Override
            public void call(Object o) {
                Log.d("call", (String) o);
            }
        });

转换还有:flatMapIterable对原来的数据进行打包发送,
concatMap放回有次序的observable
switchMap只发送最新数据,一般有延时才能看出来。
过滤:filter,自己设置过滤条件来过滤掉observable发送的数据,下面这个例子是过滤掉长度小于等于3的字符串。

Observable.just("123","abcd").filter(new Func1<String, Boolean>() {
            @Override
            public Boolean call(String s) {
                if(s.length()>3) return true;
                return false;
            }
        }).subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d("call",s);
            }
        });

take,取前几项,其他的过滤掉,takelast则是取后几项

Observable.just("123","abcd").take(1)
        .subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d("call",s);
            }
        });

skip,与take相反,过滤掉前几项,其他保留,skiplast过滤掉后几项。与take用法一样
elementAt,只发送第几项,其他过滤。与take用法一样。
distinct去除重复项,distinctUtilChanged去除相邻重复项,它们不需要传参,直接调用。
合并:
merge,合并两个observable对象,头尾先接的合并,然后发送。

Subscription sub= Observable.merge(Observable.just(1,2),Observable.just(3,4))
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        Log.d("merge", String.valueOf(integer));
                    }
                });
        sub.unsubscribe();

在这个例子中,其实observable调用订阅方法subscribe是会返回一个订阅对象subscription的,拿到这个对象有什么好处呢?就是我可以随时取消掉订阅。
zip:将里面的多个observable按自己的方式结合起来,每个observable的第i个数据结合,以数据最少的那个observable为准,其他observable多余数据舍弃。如下述例子的log为 a1和b2,c舍弃了。

Observable.zip(Observable.just(1, 2, 3), Observable.just("a", "b"), new Func2<Integer, String, Object>() {
            @Override
            public Object call(Integer integer, String s) {
                return s+integer;
            }
        }).subscribe(new Action1<Object>() {
            @Override
            public void call(Object o) {
                Log.d("zip", (String) o);
            }
        });
  • Scheduler线程控制
    上述写了怎么多,感觉都没什么用,那是还没有用上Rxjava最关键的技术-异步。Rxjava的强大之处可以指定在什么线程进行什么操作。介绍两个方法
    subscribeOn():用于指定事件产生的线程,也就是被观察者所处的线程,像文件访问、网络请求的时候被观察者进行阻塞操作,就需要用它指定线程。
    observeOn():用于指定事件消费的线程,也就是观察者所处的线程,对于上述阻塞操作的结果处理需要用它指定线程,通常是主线程。
    方法里面的参数即所指线程用这么几个:
    Schedulers.immediate():当前线程,默认都是当前线程
    Schedulers.newThread():开启一个新的线程
    Schedulers.io():IO操作所用的线程
    AndroidSchedulers.mainThread():主线程。
 Observable.just(1,2)
                .subscribeOn(Schedulers.newThread())//触发事件在新线程中执行
                .observeOn(Schedulers.newThread())//之后的操作都在新线程执行
                .map(new Func1<Integer, Object>() {
            @Override
            public Object call(Integer integer) {
                return null;
            }
        }).subscribe(new Action1<Object>() {
            @Override
            public void call(Object o) {
            }
        });

其实observeOn是指定后续所有操作的线程,如上述例子,加入我消费事件和map不想在同一线程怎么办呢?那么只要在subscribe方法之前再调用一次方法指定线程就可以了。也就是说可以多次调用observeOn方法来切换线程。
看到这里是不是感觉Rxjava特别强大。
这里只介绍了部分常用的操作符,想要知道更多操作符可以查看文档:Rxjava文档,不想看文档就自行百度Rxjava操作符大全吧。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值