RxJava RxAndroid 理论结合实践
来源:互联网 发布:luajit windows 编辑:程序博客网 时间:2024/06/14 14:51
1 操作符的使用
1、merge操作符,合并观察对象
Observable observable1 = Observable.just(6,7,8) ; Observable observable2 = Observable.just("a","b","c") ; //合并数据 先发送observable2的全部数据,然后发送 observable1的全部数据 Observable observable = Observable.merge( observable2 , observable1 ) ; observable.subscribe(new Action1() { @Override public void call(Object o) { Log.e("call==",""+o); } });
2、zip 操作符,合并多个观察对象的数据。并且允许 Func2()函数重新发送合并后的数据
Observable observable1 = Observable.just("6","7","8") ; Observable observable2 = Observable.just("a","b","c") ; Observable observable3 = Observable.zip(observable1, observable2, new Func2<String , String , String >() { @Override public String call(String s1 , String s2 ) { return s1 + s2 ; } }) ; observable3.subscribe(new Action1() { @Override public void call(Object o) { Log.e( "zip-- ",""+ o ); } }) ;
3 scan累加器操作符的使用
Observable observable = Observable.just( 1 , 2 , 3 , 4 , 5 ) ; observable.scan(new Func2<Integer,Integer,Integer>() { @Override public Integer call(Integer o, Integer o2) { return o + o2 ; } }).subscribe(new Action1() { @Override public void call(Object o) { Log.e( "scan-- ",""+o ); } });
4 filter 过滤操作符的使用
Observable observable = Observable.just( 1 , 2 , 3 , 4 , 5 , 6 , 7 ) ; observable.filter(new Func1<Integer , Boolean>() { @Override public Boolean call(Integer o) { //数据大于4的时候才会被发送 return o > 4 ; } }).subscribe(new Action1() { @Override public void call(Object o) { Log.e( "filter-- ",""+ o ); } });
5 消息数量过滤操作符的使用
* take :取前n个数据
* takeLast:取后n个数据
* first 只发送第一个数据
* last 只发送最后一个数据
* skip() 跳过前n个数据发送后面的数据
* skipLast() 跳过最后n个数据,发送前面的数据
//take 发送前3个数据 Observable observable = Observable.just( 1 , 2 , 3 , 4 , 5 , 6 , 7 ) ; observable.take( 3 ) .subscribe(new Action1() { @Override public void call(Object o) { Log.e( "take-- ","" +o ); } }) ; //takeLast 发送最后三个数据 Observable observable2 = Observable.just( 1 , 2 , 3 , 4 , 5 , 6 , 7 ) ; observable2.takeLast( 3 ) .subscribe(new Action1() { @Override public void call(Object o) { Log.e( "takeLast-- ","" +o ); } }) ; //first 只发送第一个数据 Observable observable3 = Observable.just( 1 , 2 , 3 , 4 , 5 , 6 , 7 ) ; observable3.first() .subscribe(new Action1() { @Override public void call(Object o) { Log.e( "first-- ","" +o ); } }) ; //last 只发送最后一个数据 Observable observable4 = Observable.just( 1 , 2 , 3 , 4 , 5 , 6 , 7 ) ; observable4.last() .subscribe(new Action1() { @Override public void call(Object o) { Log.e( "last-- ","" +o ); } }) ; //skip() 跳过前2个数据发送后面的数据 Observable observable5 = Observable.just( 1 , 2 , 3 , 4 , 5 , 6 , 7 ) ; observable5.skip( 2 ) .subscribe(new Action1() { @Override public void call(Object o) { Log.e( "skip-- ","" +o ); } }) ; //skipLast() 跳过最后两个数据,发送前面的数据 Observable observable6 = Observable.just( 1 , 2 , 3 , 4 , 5 , 6 , 7 ) ; observable6.skipLast( 2 ) .subscribe(new Action1() { @Override public void call(Object o) { Log.e( "skipLast-- ","" +o ); } }) ;
6 elementAt 、elementAtOrDefault
//elementAt() 发送数据序列中第n个数据 ,序列号从0开始 //如果该序号大于数据序列中的最大序列号,则会抛出异常,程序崩溃 //所以在用elementAt操作符的时候,要注意判断发送的数据序列号是否越界 int s = 6; List<Integer> list = new ArrayList<>(); for (int i = 0; i < 7; i++) { list.add(i); } if(s >= list.size()){ Log.e("elementAt","角标越界了"); }else { Observable observable7 = Observable.from(list); observable7.elementAt(s) .subscribe(new Action1() { @Override public void call(Object o) { Log.e("elementAt-- ", "" + o); } }); } //elementAtOrDefault( int n , Object default ) 发送数据序列中第n个数据 ,序列号从0开始。 //如果序列中没有该序列号,则发送默认值 Observable observable9 = Observable.just( 1 , 2 , 3 , 4 , 5 ) ; observable9.elementAtOrDefault( 8 , 666 ) .subscribe(new Action1() { @Override public void call(Object o) { Log.e( "elementAtOrDefault-- ",""+ o ); } }) ;
7 startWith() 插入数据
//插入普通数据 //startWith 数据序列的开头插入一条指定的项 , 最多插入9条数据 Observable observable = Observable.just( "aa" , "bb" , "cc" ) ; observable .startWith( "dd" , "ee" ) .subscribe(new Action1() { @Override public void call(Object o) { Log.e( "startWith-- ",""+ o ); } }) ; //插入Observable对象 List<String> list = new ArrayList<>() ; list.add( "ff" ) ; list.add( "gg" ) ; observable.startWith( Observable.from( list )) .subscribe(new Action1() { @Override public void call(Object o) { Log.e( "startWith2 -- ",""+ o ); } }) ;
8 delay操作符,延迟数据发送
Observable<String> observable = Observable.just( "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8" ) ; //延迟数据发射的时间,仅仅延时一次,也就是发射第一个数据前延时。发射后面的数据不延时 observable.delay( 3 , TimeUnit.SECONDS ) //延迟3秒钟 .subscribe(new Action1() { @Override public void call(Object o) { Log.e("delay-- ",""+ o); } }) ;
9 Timer 延时操作符的使用
//5秒后输出 hello world , 然后显示一张图片 Observable.timer( 5 , TimeUnit.SECONDS ) .observeOn(AndroidSchedulers.mainThread() ) .subscribe(new Action1<Long>() { @Override public void call(Long aLong) { Log.e( "timer--hello world ",""+aLong ); } }) ;
delay 、timer 总结:
相同点:delay 、 timer 都是延时操作符。
不同点:delay 延时一次,延时完成后,可以连续发射多个数据。timer延时一次,延时完成后,只发射一次数据。
10 interval 轮询操作符,循环发送数据,数据从0开始递增
//参数一:延迟时间 参数二:间隔时间 参数三:时间颗粒度
Observable observable = Observable.interval(3000, 1000, TimeUnit.MILLISECONDS) ; Subscription subscription = observable.subscribe(new Action1() { @Override public void call(Object o) { Log.e( "interval- ","" + o ); } }) ;
11 doOnNext() 操作符,在每次 OnNext() 方法被调用前执行
使用场景:从网络请求数据,在数据被展示前,缓存到本地
Observable observable = Observable.just( "1" , "2" , "3" , "4" ) ; observable.doOnNext(new Action1() { @Override public void call(Object o) { Log.e( "doOnNext--缓存数据",""+ o ); } }).subscribe(new Observer() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(Object o) { Log.e( "onNext--",""+ o ); } }) ;
12 Buffer 操作符
Buffer( int n ) 把n个数据打成一个list包,然后再次发送。
Buffer( int n , int skip) 把n个数据打成一个list包,然后跳过第skip个数据。
List<String> list = new ArrayList<>(); for (int i = 1; i < 10; i++) { list.add("" + i); } Observable<String> observable = Observable.from(list); observable .buffer(2) //把每两个数据为一组打成一个包,然后发送 .subscribe(new Action1<List<String>>() { @Override public void call(List<String> strings) { Log.e("call","buffer---------------" ); Observable.from( strings ).subscribe(new Action1<String>() { @Override public void call(String s) { Log.e( "buffer data --", s); } }) ; } });
13、throttleFirst 操作符
使用场景:1、button按钮防抖操作,防连续点击 2、百度关键词联想,在一段时间内只联想一次,防止频繁请求服务器
Observable.interval( 1 , TimeUnit.SECONDS) .throttleFirst( 3 , TimeUnit.SECONDS ) .subscribe(new Action1<Long>() { @Override public void call(Long aLong) { Log.e( "throttleFirst--",""+aLong ); } }) ;
14 distinct 过滤重复的数据
List<String> list = new ArrayList<>() ; list.add( "1" ) ; list.add( "2" ) ; list.add( "1" ) ; list.add( "3" ) ; list.add( "4" ) ; list.add( "2" ) ; list.add( "1" ) ; list.add( "1" ) ; Observable.from( list ) .distinct() .subscribe(new Action1<String>() { @Override public void call(String s) { Log.e( "distinct--",s ); } }) ;
15 debounce() 操作符
一段时间内没有变化,就会发送一个数据。
16 doOnSubscribe()
使用场景: 可以在事件发出之前做一些初始化的工作,比如弹出进度条等等
注意:
1、doOnSubscribe() 默认运行在事件产生的线程里面,然而事件产生的线程一般都会运行在 io 线程里。那么这个时候做一些,更新UI的操作,是线程不安全的。所以如果事件产生的线程是io线程,但是我们又要在doOnSubscribe() 更新UI , 这时候就需要线程切换。
2、如果在 doOnSubscribe() 之后有 subscribeOn() 的话,它将执行在离它最近的 subscribeOn() 所指定的线程。
3、 subscribeOn() 事件产生的线程 ; observeOn() : 事件消费的线程
Observable.create(onSubscribe) .subscribeOn(Schedulers.io()) .doOnSubscribe(new Action0() { @Override public void call() { progressBar.setVisibility(View.VISIBLE); // 需要在主线程执行 } }) .subscribeOn(AndroidSchedulers.mainThread()) // 指定主线程 .observeOn(AndroidSchedulers.mainThread()) .subscribe(subscriber);
17、range 操作符的使用
Range操作符发射一个范围内的有序整数序列,你可以指定范围的起始和长度。
RxJava将这个操作符实现为range函数,它接受两个参数,一个是范围的起始值,一个是范围的数据的数目。如果你将第二个参数设为0,将导致Observable不发射任何数据(如果设置为负数,会抛异常)。
range默认不在任何特定的调度器上执行。有一个变体可以通过可选参数指定Scheduler。
Observable.range( 10 , 3 ) .subscribe(new Action1<Integer>() { @Override public void call(Integer integer) { Log.v( "rx_range " , "" + integer ) ; } }) ;
18、defer 操作符
i = "11 " ; Observable<String> defer = Observable.defer(new Func0<Observable<String>>() { @Override public Observable<String> call() { return Observable.just( i ) ; } }) ; Observable test = Observable.just( i ) ; i = "12" ; defer.subscribe(new Action1<String>() { @Override public void call(String s) { Log.e( "rx_defer " , "" + s ) ; } }) ; test.subscribe(new Action1() { @Override public void call(Object o) { Log.e( "rx_just " , "" + o ) ; } }) ;
可以看到,just操作符是在创建Observable就进行了赋值操作,而defer是在订阅者订阅时才创建Observable,此时才进行真正的赋值操作。
2 生命周期控制和内存优化
RxJava使我们很方便的使用链式编程,代码看起来既简洁又优雅。但是RxJava使用起来也是有副作用的,使用越来越多的订阅,内存开销也会变得很大,稍不留神就会出现内存溢出的情况
1、取消订阅 subscription.unsubscribe() ;
private void subscribe() { subscription = Observable.just( "123").subscribe(new Action1<String>() { @Override public void call(String s) { Log.e( "tt--", s ); } }) ; } @Override protected void onDestroy() { super.onDestroy(); if(subscription!=null){ subscription.unsubscribe(); } }
2、线程调度
Scheduler调度器,相当于线程控制器
Schedulers.immediate() : 直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler。
Schedulers.newThread() :总是启用新线程,并在新线程执行操作.
Schedulers.io():I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。
Schedulers.computation() : 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。
还有RxAndroid里面专门提供了AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行。
常见的场景:为了不阻塞UI,在子线程加载数据,在主线线程显示数据
Observable.just( "1" , "2" , "3" ) .delay(2,TimeUnit.SECONDS) .subscribeOn(Schedulers.io()) //指定 subscribe() 发生在 IO 线程 .observeOn( AndroidSchedulers.mainThread() ) //指定 Subscriber 的回调发生在主线程 .subscribe(new Action1<String>() { @Override public void call(String s) { ((TextView)findViewById(R.id.text)).setText( s ); } }) ;
Scheduler 自由多次切换线程。恩,这个更为牛逼
observeOn() 可以调用多次来切换线程,observeOn 决定他下面的方法执行时所在的线程。
subscribeOn() 用来确定数据发射所在的线程,位置放在哪里都可以,但它是只能调用一次的。
Observable.just(1, 2, 3, 4) // IO 线程,由 subscribeOn() 指定 .subscribeOn(Schedulers.io()) .observeOn(Schedulers.newThread()) .map(new Func1<Integer, String>() { @Override public String call(Integer integer) { return integer +"66"; } }) // 新线程,由 observeOn() 指定 .observeOn(Schedulers.io()) // IO 线程,由 observeOn() 指定 .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<String>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { Log.e("onNext==",s); } }); // Android 主线程,由 observeOn() 指定
线程调度
例1
Observable .create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { Log.e("rx_call", Thread.currentThread().getName()); subscriber.onNext( "dd"); subscriber.onCompleted(); } }) .map(new Func1<String, String >() { @Override public String call(String s) { Log.e( "rx_map" , Thread.currentThread().getName() ); return s + "88"; } }) .subscribe(new Action1<String>() { @Override public void call(String s) { Log.e( "rx_subscribe" , Thread.currentThread().getName() ); Log.e( "rx_subscribe" , s ); } }) ;
例2
new Thread(new Runnable() { @Override public void run() { Log.e( "rx_newThread" , Thread.currentThread().getName() ); rx(); } }).start(); private void rx(){ Observable .create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { Log.e( "rx_call" , Thread.currentThread().getName() ); subscriber.onNext( "dd"); subscriber.onCompleted(); } }) .map(new Func1<String, String >() { @Override public String call(String s) { Log.e( "rx_map" , Thread.currentThread().getName() ); return s + "88"; } }) .subscribe(new Action1<String>() { @Override public void call(String s) { Log.e( "rx_subscribe" , Thread.currentThread().getName() ); } }) ; }
例3
Observable .create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { Log.e( "rx_call" , Thread.currentThread().getName() ); subscriber.onNext( "dd"); subscriber.onCompleted(); } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map(new Func1<String, String >() { @Override public String call(String s) { Log.e( "rx_map" , Thread.currentThread().getName() ); return s + "88"; } }) .subscribe(new Action1<String>() { @Override public void call(String s) { Log.e( "rx_subscribe" , Thread.currentThread().getName() ); } }) ;
例4
map() 操作符默认运行在事件产生的线程之中。事件消费只是在 subscribe() 里面
Observable .create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { Log.e( "rx_call" , Thread.currentThread().getName() ); subscriber.onNext( "dd"); subscriber.onCompleted(); } }) .map(new Func1<String, String >() { @Override public String call(String s) { Log.e( "rx_map" , Thread.currentThread().getName() ); return s + "88"; } }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<String>() { @Override public void call(String s) { Log.e( "rx_subscribe" , Thread.currentThread().getName() ); } }) ;
create() , just() , from() 等 — 事件产生
map() , flapMap() , scan() , filter() 等 – 事件加工
subscribe() – 事件消费
事件产生:默认运行在当前线程,可以由 subscribeOn() 自定义线程
事件加工:默认跟事件产生的线程保持一致, 可以由 observeOn() 自定义线程
事件消费:默认运行在当前线程,可以有observeOn() 自定义
例5 多次切换线程
Observable .create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { Log.e( "rx_call" , Thread.currentThread().getName() ); subscriber.onNext( "dd"); subscriber.onCompleted(); } }) .observeOn( Schedulers.newThread() ) //新线程 .map(new Func1<String, String >() { @Override public String call(String s) { Log.e( "rx_map" , Thread.currentThread().getName() ); return s + "88"; } }) .observeOn( Schedulers.io() ) //io线程 .filter(new Func1<String, Boolean>() { @Override public Boolean call(String s) { Log.e( "rx_filter" , Thread.currentThread().getName() ); return s != null ; } }) .subscribeOn(Schedulers.io()) //定义事件产生线程:io线程 .observeOn(AndroidSchedulers.mainThread()) //事件消费线程:主线程 .subscribe(new Action1<String>() { @Override public void call(String s) { Log.e( "rx_subscribe" , Thread.currentThread().getName() ); } }) ;
例6:只规定事件产生的线程
Observable .create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { Log.e( "rx--create " , Thread.currentThread().getName() ) ; subscriber.onNext( "dd" ) ; } }) .subscribeOn(Schedulers.io()) .subscribe(new Action1<String>() { @Override public void call(String s) { Log.e( "rx--subscribe " , Thread.currentThread().getName() ) ; } }) ;
例:7:只规定事件消费线程
Observable .create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { Log.e( "rx--create " , Thread.currentThread().getName() ) ; subscriber.onNext( "dd" ) ; } }) .observeOn( Schedulers.newThread() ) .subscribe(new Action1<String>() { @Override public void call(String s) { Log.e( "rx--subscribe " , Thread.currentThread().getName() ) ; } }) ;
例8:线程调度封装
public class RxUtil { private final static Observable.Transformer schedulersTransformer = new Observable.Transformer() { @Override public Object call(Object observable) { return ((Observable) observable).subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()); } }; public static <T> Observable.Transformer<T, T> applySchedulers() { return (Observable.Transformer<T, T>) schedulersTransformer; }}Observable.just( "123" ) .compose( RxUtil.<String>applySchedulers() ) .subscribe(new Action1() { @Override public void call(Object o) { Log.e("call==",""+o); } }) ;
源代码下载
- RxJava RxAndroid 理论结合实践
- RxJava RxAndroid Retrofit实践结合
- Android RxJava/RxAndroid结合Retrofit使用
- rxjava/rxandroid结合lambda的使用
- Rxjava与Rxandroid结合实现网络请求
- RxJava & RxAndroid
- RxAndroid+RxJava
- RxJava /RxAndroid
- RxJava+Retrofit+okhttp实践结合
- RxJava+RxAndroid+MVP入坑实践(一:基础篇)
- RxJava+RxAndroid+MVP入坑实践(一:基础篇)
- RxJava 与 Retrofit 结合的最佳实践
- RxJava 与 Retrofit 结合的最佳实践
- RxJava 与 Retrofit 结合的最佳实践
- Retrofit结合RxJava的一次实践
- RxJava 与 Retrofit 结合的最佳实践
- RxJava 与 Retrofit 结合的最佳实践
- RxJava 与 Retrofit 结合的最佳实践
- UE4播放视频
- KMP算法及next数组详解
- 关于渠道包的不完美之处
- Java8 新特性之八---------类依赖分析器:jdeps
- Android开发规范总结
- RxJava RxAndroid 理论结合实践
- 新政之后,黑车卷土重来的日子还远吗?
- 数据结构基础之—栈
- openCascade学习资料
- 文章标题
- linux目录
- tablayout底部导航栏
- 资源整理
- JS 面向对象