Rxjava2.x很详细的介绍

来源:互联网 发布:汕头峡山淘宝拍摄 编辑:程序博客网 时间:2024/06/03 23:04

Rxjava详解

  1. Rxjava的优点:

    • 链式调用,代码调用流程异常清晰 ,代码简洁。
    • RxJava和EventBus一样也是基于观察者模式,但是使用的场景确实异步数据流的处理
    • RxJava更加强大,利用操作符它可以对发出的消息进行一系列的变换
  2. 引入依赖:

       compile 'io.reactivex.rxjava2:rxjava:2.0.1'       compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
  1. RxJava到底是什么?

    Rxjava的是通过一种扩展的观察者设计模式来实现异步操作,跟AsyncTask和Handler类似,但是比AsyncTask和Handler更加简洁随着程序逻辑变得越来越复杂,它依然能够保持逻辑的简洁。

  2. 基本实现
    (1) 创建观察者Observer,它决定事件触发的时候该有的行为。

       private Observer<String> observer = new Observer<String>() {            @Override            public void onSubscribe(Disposable d) {                //RxJava 2.0 中新增的,传递参数为Disposable ,Disposable 相当于1.x中的Subscription,调用d.dispose()解除绑定            }            @Override            public void onNext(String value) {            }            @Override            public void onError(Throwable e) {                //在事件处理过程中出异常时,onError()会被触发            }            @Override            public void onComplete() {                //事件队列完结时调用该方法            }        };
(2) 创建被观察者Observable,它决定什么时候以及怎样触发事件 
    Observable observable = Observable.create(new ObservableOnSubscribe<String>() {                @Override                public void subscribe(ObservableEmitter<String> e) throws Exception {                    e.onNext("A");                    e.onNext("B");                    //onError和onComplete()只能调用其中一个                    e.onComplete();                }    });

Observable的其他创建方式

  //just方式创建    Observable<String> observable = Observable.just("Hello","A");
    //fromIterable()用于集合数据,fromArray()用于数组数据方式,    List<String> array1=new ArrayList<>();    array1.add("F");    array1.add("G");    Observable.fromIterable(array1).subscribe(observer);
    //创建一个按固定时间间隔发射整数序列的Observable,可用作定时器。即按照固定2秒一次调用onNext()方法。    Observable<Long> interval = Observable.interval(2, TimeUnit.SECONDS);

(3) 订阅

    //创建了 Observable 和 Observer 之后,再用 subscribe() 方法将它们联结起来    //被观察者订阅观察者,符合流式代码的结构    mObservable.subscribe(observer);
(5) 简洁的写法:
        String[] word= new String[]{"hello", "world", "chinses"};        Disposable subscribe = Observable.fromAray(word).subscribe(new Consumer<String>() {                @Override                public void accept(String aLong) throws Exception {                    //相当于Observer的onNext()                    Log.i(TAG, "accept: " + aLong);                }            }, new Consumer<Throwable>() {                @Override                public void accept(Throwable throwable) throws Exception {                    //相当于Observer的onError()                    Log.i(TAG, "onError: ");                }            }, new Action() {                @Override                public void run() throws Exception {                    //相当于Observer的onComplete()                    Log.i(TAG, "onComplete: ");                }            });        subscribe.dispose();//取消订阅
另外我们需要明白两点:1.Observable和Observer可以做任何事情   Observable可以是一个数据库查询,Observer用来显示查询结果(传递数据);Observable可以是屏幕上的点击事件,   Observer用来响应点击事件(传递事件);Observable可以是一个网络请求,Observer用来显示请求结果。2.Observable和Observer是独立于中间的变换过程的。   在Observable和Observer中间可以增减任何数量的操作符。整个系统是高度可组合的,操作数据是一个很简单的过程 
  1. 操作符:

    作用:将事件序列中的对象或整个序列进行加工处理,转换层不同的事件或事件序列

    • filter() :可以对Observable流程的数据进行一层过滤处理,返回一个新的Observable,filter()返回为false的值将不会发出到Subscriber。
    Observable.just("A").map(new Function<String, Integer>() {                @Override                public Integer apply(String s) throws Exception {                    return s.length();                }            }).filter(new Predicate<Integer>() {                @Override                public boolean test(Integer integer) throws Exception {                    return integer != 10;                }            }).subscribe(new Consumer<Integer>() {                @Override                public void accept(Integer integer) throws Exception {                    Log.i(TAG, "accept: " + integer);                }            });
  • map(): 事件对象的直接变换,一个Observable对象上可以多次使用map操作符
    Observable.just("images/logo.png") // 输入类型 String     .map(new Function<String, Bitmap>() {         @Override         public Bitmap apply(String filePath) { // 参数类型 String             return getBitmapFromPath(filePath); // 返回类型 Bitmap         }     }).subscribe(new Consumer<Bitmap>() {                @Override                public void accept(Bitmap bitmap) throws Exception {                    showBitmap(bitmap);                }     });
  • flatMap():flatMap() 和 map() 有一个相同点:它也是把传入的参数转化之后返回另一个对象,不同的是, flatMap() 中返回的是个 Observable 对象。
     //有方法根据输入的字符串返回一个List集合信息     Observable<List<String>> query(String text);      //假如不用flatMap()我们应该这样写:       query("message")      .subscribe(new Function<List<String>>() {            @Override            public void apply(List<String> mLists) {               Observable.fromIterable(mLists)                 .subscribe(new Consumer<String>() {                @Override                public void accept(String message) {                      log.i(TAG,message);                           }             });                }      }); 
使用flatMap()这样写:
 query("Hello, world!")      .flatMap(new Function<List<String>, Observable<String>>() {          @Override          public Observable<String> apply(List<String> urls) {              return Observable.from(urls);          }      })      .subscribe(new Consumer<String>() {                @Override                public void accept(String message) {                      log.i(TAG,message);                           }    });

扩展:嵌套的异步请求,第一个网络请求获取第二个网络请求所需要的参数

    networkClient.token() // 返回 Observable<String>,在订阅时请求 token,并在响应后发送 token        .flatMap(new Function<String, Observable<Messages>>() {            @Override            public Observable<Messages> apply(String token) {                // 返回 Observable<Messages>,在订阅时请求消息列表,并在响应后发送请求到的消息列表                return networkClient.messages(token);            }        }        .subscribeOn(Schedulers.io())        .observeOn(AndroidSchedulers.mainThread())        .subscribe(new Consumer<Messages>() {            @Override            public void accept(Messages messages) {                // 处理显示消息列表                showMessages(messages);            }        });
  • doOnNext()

    输出元素的准备工作,一般用于获取网络数据后保存到数据库的操作,因为数据库操作是耗时任务需要在子线程执行

            Observable.fromIterable(arrayList).flatMap(new Function<List<String>, Observable<String>>() {                @Override                public Observable<String> apply(List<String> strings) throws Exception {                    return Observable.fromIterable(strings);                }            }).doOnNext(new Consumer<String>() {                @Override                public void accept(String s) throws Exception {                    Log.i(TAG, "输出元素之前的准备工作: "+s);                }            })            .subscribeOn(Schedulers.io())                 .observeOn(AndroidSchedulers.mainThread())            .subscribe(new Consumer<String>() {                @Override                public void accept(String s) throws Exception {                    Log.i(TAG, "accept: " + s);                }            });
  • doOnSubscribe()

    Observable.doOnSubscribe() 。它和 Subscriber.onStart() 同样是在 subscribe() 调用后而且在事件发送前执行,但区别在于它可以指定线程。默认情况下, doOnSubscribe() 执行在 subscribe() 发生的线程;而如果在 doOnSubscribe() 之后有 subscribeOn() 的话,它将执行在离它最近的 subscribeOn() 所指定的线程。

            Observable.fromIterable(arrayList).flatMap(new Function<List<String>, Observable<String>>() {                @Override                public Observable<String> apply(List<String> strings) throws Exception {                    Log.i(TAG, "flatMap操作: ");                    return Observable.fromIterable(strings);                }            })            .subscribeOn(Schedulers.io())            .doOnSubscribe(new Consumer<Disposable>() {                @Override                public void accept(Disposable disposable) throws Exception {                    Log.i(TAG, "事件发送之前:比如请求网络之前ProgressBar转圈操作");                }            })            .subscribeOn(AndroidSchedulers.mainThread()) // 指定主线程            .observeOn(Schedulers.io())            .doOnNext(new Consumer<String>() {                @Override                public void accept(String s) throws Exception {                    Log.i(TAG, "输出元素之前的准备工作: "+s);                }            })            .observeOn(AndroidSchedulers.mainThread())            .subscribe(new Consumer<String>() {                @Override                public void accept(String s) throws Exception {                    Log.i(TAG, "accept: " + s);                }            });            //事件打印结果            com.liujian.rxjava I/MainActivity: 事件发送之前:比如请求网络之前ProgressBar转圈操作            com.liujian.rxjava I/MainActivity: flatMap操作:             com.liujian.rxjava I/MainActivity: 输出元素之前的准备工作: A            com.liujian.rxjava I/MainActivity: accept: A            com.liujian.rxjava I/MainActivity: flatMap操作:             com.liujian.rxjava I/MainActivity: accept: B            com.liujian.rxjava I/MainActivity: 输出元素之前的准备工作: C            com.liujian.rxjava I/MainActivity: accept: C
  1. 线程控制-Scheduler(线程调度器)

    在默认情况下,即在不指定线程的情况下,RxJava遵循的是在哪个线程生产事件,就在哪个线程消费事件

    • 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 主线程运行。
   Observable.just(1,2,3,4)          .subscribeOn(Schedulers.io()) //改变调用它之前代码的线程          .observeOn(AndroidSchedulers.mainThread()) //改变调用它之后代码的线程          .subscribe(new Consumer<Integer>() {              @Override              public void accept(Integer integer) throws Exception {                 //主线程显示数据              }          });
  1. 线程控制-Scheduler(二)

    实现线程的多次切换

    注意:不同于 observeOn() , subscribeOn() 的位置放在哪里都可以,但它是只能调用一次的。

        Observable.just(R.mipmap.ic_launcher)              .subscribeOn(Schedulers.io())//指定Observable的操作运行在io()中              .observeOn(Schedulers.newThread())//指定map运行于newThread()中              .map(new Function<Integer, Drawable>() {                    @Override                    public Drawable apply(Integer integer)throws Exception  {                        return getResources().getDrawable(integer);                    }                })              .observeOn(AndroidSchedulers.mainThread())//指定Subscriber的代码运行在主线程              .subscribe(new Consumer<Drawable>() {                    @Override                    public void accept(Drawable drawable) throws Exception {                        iv_iamgeview.setImageDrawable(drawable);                    }                });
  1. 使用场景和使用方式
- 与Retrofit结合使用      getUser(userId)          //接口返回数据后把数据存到数据库,当onNext发生时,它被调用,不改变数据流。          .doOnNext(new Consumer<User>() {              @Override              public void accept(User user) {                  saveOrUpdate2Db(user);              })          .subscribeOn(Schedulers.io())               .observeOn(AndroidSchedulers.mainThread())          .subscribe(new Subscriber<User>() {              @Override              public void onNext(User user) {                  userView.setUser(user);              }              @Override              public void onCompleted() {              }              @Override              public void onError(Throwable error) {                  // Error handling                  ...              }          });
  1. Disposable简介

     在RxJava中,用它来切断Observer(观察者)与Observable(被观察者)之间的连接,当调用它的dispose()方法时, 

    它就会将Observer(观察者)与Observable(被观察者)之间的连接切断, 从而导致Observer(观察者)收不到事件。

     注意:当切断被观察者与观察者之间的联系,Observable(被观察者)的事件却仍在继续执行。
  2. Flowable/Subscriber

    Observable和Observer的观察者模式是不支持背压的。所以,当我们使用Observable/Observer的时候,我们需要考虑的是,数据量是不是很大(官方给出以1000个事件为分界线,仅供各位参考)

    背压:事件产生的速度远远快于事件消费的速度,最终导致数据积累越来越多,从而导致OOM等异常。

    需要强调两点:

    • 背压策略的一个前提是异步环境,也就是说,被观察者和观察者处在不同的线程环境中。
    • 背压(Backpressure)并不是一个像flatMap一样可以在程序中直接使用的操作符,他只是一种控制事件流速的策略。

    /* 背压(在异步过程中,由于被观察者发射数据过快,而观察者处理数据不及时, * 导致内存里堆积了太多数据,从而OOM,可以选择不同的策略处理该问题) * Flowable对应subscriber */

    private void createFlowable() {         Flowable<String> flowable = Flowable.create(new FlowableOnSubscribe<String>() {                                           @Override             public void subscribe(FlowableEmitter<String> e) throws Exception {                    if (!e.isCancelled()) {                      e.onNext("This");                      e.onNext("is");                      e.onNext("RxJava");                      e.onComplete(); }               } //抛弃策略 }, BackpressureStrategy.DROP);         Subscriber<String> subscriber = new Subscriber<String>() {               Subscription subscription;                @Override               public void onSubscribe(Subscription s) {                  subscription = s; //请求一个数据                 subscription.request(1);                }                @Override                public void onNext(String s) {                   Log.i(TAG, "onNext: " + s); //处理完后,再请求一个数据                   subscription.request(1);                }                @Override                public void onError(Throwable e) {                   Log.i(TAG, "onError: " + e.getLocalizedMessage());               }                @Override                public void onComplete() {                    Log.i(TAG, "onComplete"); //取消订阅                    subscription.cancel(); }               };         flowable.subscribe(subscriber);       }
原创粉丝点击