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);            }        }) ;

源代码下载

0 0
原创粉丝点击