RxAndroid菜鸟必入

来源:互联网 发布:淘宝网信鸽鸽具用品 编辑:程序博客网 时间:2024/05/17 21:19

为啥要学RxAndroid呢,因为我要用Retrofit,就这么简单粗暴;除了Rx还有OkHtpp3;接下来都会说的。不要着急~

给Android开发者的Rx详解建议看看这篇文章,看过之后会就会都明白了 。

一、基本概念和添加依赖

  • Observer(观察者):事件触发的时候有什么样的行为;
  • Observable(被观察者):决定什么时候触发事件,以及触发怎样的事件;
  • subscribe(订阅):建立Observer和Observable之间的关联。

----》(被观察者要做什么之前告诉观察者我要做什么了,你做好准备,等被观察者行动时,观察者采取自己相应的动作,在这之前要有观察者和被观察者,还要建立它们之间的关系,要不怎么通话呀,怎么告诉要干啥了)

这里所说的事件主要有:

  • 1、onNext:相当于onClick、onEvent;
  • 2、onCompleted:事件队列完成;
  • 3、onError:队列异常,队列终止,不会有事件发出

注意:onError和onComplete两者是互斥的,有且只能有一个,并且是事件序列的最后一个
在app的gradle.build中添加:compile ‘io.reactivex:rxandroid:1.0.1’

二、创建Observer、Observable、Subscribe

  • 1、使用Observer类创建Observer
/**     * 观察者的作用:事件触发的时候将有怎样的行为     */    private void createObserver() {        Observer<String> stringObserver = new Observer<String>() {            @Override            public void onCompleted() {            }            @Override            public void onError(Throwable e) {            }            @Override            public void onNext(String s) {            }        };    }
  • 2、使用Subscriber类创建Observer
//创建Observer的扩展类,Subscriber是实现了Observer的抽象类    private void expanObserver() {        Subscriber<String> stringSubscriber = new Subscriber<String>() {            @Override            public void onCompleted() {            }            @Override            public void onError(Throwable e) {            }            @Override            public void onNext(String s) {            }            @Override            public void onStart() {                super.onStart();            }        };    }
  • 3、Observer和Subscriber关系

关联:
实质上,在 RxJava 的 subscribe 过程中,Observer 也总是会先被转换成一个 Subscriber
再使用。所以如果你只想使用基本功能,选择 Observer 和 Subscriber 是完全一样的。

区别:
1)、onStart():这是 Subscriber增加的方法。它会在subscribe刚开始,而事件还未发送之前被调用,可以用于做一些准备工作,例如数据的清零或重置。这是一个可选方法,默认情况下它的实现为空。需要注意的是,如果对准备工作的线程有要求(例如弹出一个显示进度的对话框,这必须在主线程执行),
onStart()就不适用了,因为它总是在 subscribe所发生的线程被调用,而不能指定线程。要在指定的线程来做准备工作,可以使用
doOnSubscribe()方法,具体可以在后面的文中看到。
2)、unsubscribe(): 这是Subscriber所实现的另一个接口 Subscription的方法,用于取消订阅。 在这个方法被调用后,Subscriber将不再接收事件。一般在这个方法调用前,可以使用 isUnsubscribed()先判断一下状态。 unsubscribe()这个方法很重要,因为在 subscribe() 之后, Observable会持有Subscriber的引用,这个引用如果不能及时被释放,将有内存泄露的风险。 所以最好保持一个原则:要在不再使用的时候尽快在合适的地方(例如
onPause() onStop()等方法中)调用 unsubscribe()来解除引用关系,以避免内存泄露的发生。

  • 4、创建被观察者Observable
 /**     * 被观察者的作用:决定什么时候触发事件,以及触发怎样的事件     */    private void createObservable() {        //create是创建事件序列的方法        Observable observable = Observable.create(new Observable.OnSubscribe<String>() {            //当被观察者observable被订阅的时候,该方法会自动被调用(及observable.subscribe(observer);时才真正调用)            @Override            public void call(Subscriber<? super String> subscriber) {                //观察者subscriber将会调用两次onNext()和一次onCompleted(),----》这样被观察者调用了观察者的回调方法,就实现类由被观察者向观察者的事件传递,即观察者模式                subscriber.onNext("hello");                subscriber.onNext("world");                subscriber.onCompleted();            }        });    }
  • 5、创建被观察者带参数情况
private void createOtherEventSequeue() {        //just将传入的参数依次发送出来        Observable observable_just = Observable.just("hello", "world");        //将传入的 数组 或 Iterable 拆分成具体对象后,依次发送出来。        String[] words = {"hello", "world"};        Observable observable_from = Observable.from(words);        // 以上两者都相当于下面的逻辑:        // onNext("hello");        // onNext("world");        // onCompleted();    }
  • 6、创建Subscribe
private void subscribe(){        //创建观察者        Observer<String> observer = new Observer<String>() {            @Override            public void onCompleted() {            }            @Override            public void onError(Throwable e) {            }            @Override            public void onNext(String s) {                Log.e("----------->","s"+s);            }        };        //创建被观察者        Observable<String> observable = Observable.just("hello","world");        //建立关联        observable.subscribe(observer);    }

三、线程控制Scheduler

  • 1、说明:

在不指定线程的情况下, RxJava遵循的是线程不变的原则,即:在哪个线程调用 subscribe(),就在哪个线程生产事件;
在哪个线程生产事件,就在哪个线程消费事件。如果需要切换线程,就需要用到 Scheduler(调度器)。
Scheduler ——调度器,相当于线程控制器,RxJava通过它来指定每一段代码应该运行在什么样的线程。

  • 2、RxJava提供的几种Scheduler

1)Schedulers.immediate():直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler。
2)Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。
3)Schedulers.io():I/O操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread()差不多,区别在于 io()的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io()比 newThread() 更有效率。不要把计算工作放在 io()中,可以避免创建不必要的线程。
4)Schedulers.computation():计算所使用的 Scheduler。这个计算指的是 CPU密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler使用的固定的线程池,大小为 CPU核数。不要把 I/O操作放在 computation()中,否则 I/O操作的等待时间会浪费 CPU。
5)AndroidSchedulers.mainThread():它指定的操作将在 Android主线程运行。

  • 3、有了这几个 Scheduler ,就可以使用 subscribeOn() 和 observeOn() 两个方法来对线程进行控制了。

subscribeOn():指定 subscribe()所发生的线程,即 Observable.OnSubscribe被激活时所处的线程。或者叫做事件产生的线程。
observeOn():指定 Subscriber所运行在的线程。或者叫做事件消费的线程。
注意:通过 observeOn()的多次调用,程序实现了线程的多次切换。不过,不同于 observeOn(), subscribeOn()的位置放在哪里都可以,但它是只能调用一次的。

  • 4、看看怎么使用的吧
private void scheduler() {        Observable.create(new Observable.OnSubscribe<String>() {            @Override            public void call(Subscriber<? super String> subscriber) {                Log.e("------------>","call"+",thread"+Thread.currentThread().getName());                subscriber.onNext("我就看看好用不,看看怎么用");                subscriber.onCompleted();            }        })                .subscribeOn(Schedulers.io())// 指定 subscribe() 发生在 IO 线程                .observeOn(AndroidSchedulers.mainThread()) // 指定 Subscriber 的回调发生在主线程                .subscribe(new Observer<String>() {                    @Override                    public void onCompleted() {                        Log.e("------------>","onCompleted"+",thread"+Thread.currentThread().getName());                    }                    @Override                    public void onError(Throwable e) {                    }                    @Override                    public void onNext(String s) {                        Log.e("------------>","s"+s+",thread"+Thread.currentThread().getName());                    }                });    }    private void moreScheduler(){        //通过 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 s) {                        return null;                    }                }) // 新线程,由 observeOn() 指定                .observeOn(Schedulers.io())                .map(new Func1<String, String>() {                    @Override                    public String call(String s) {                        return null;                    }                }) // IO 线程,由 observeOn() 指定                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Observer<String>() {                    @Override                    public void onCompleted() {                    }                    @Override                    public void onError(Throwable e) {                    }                    @Override                    public void onNext(String s) {                    }                });  // Android 主线程,由 observeOn() 指定    }
  • 5、doOnSubscribe()
 /**     * 在前面讲 Subscriber 的时候,提到过 Subscriber 的 onStart() 可以用作流程开始前的初始化。     * 然而 onStart() 由于在 subscribe() 发生时就被调用了,因此不能指定线程,而是只能执行在 subscribe() 被调用时的线程。     * 这就导致如果 onStart() 中含有对线程有要求的代码(例如在界面上显示一个 ProgressBar,这必须在主线程执行),将会有线程非法的风险,因为有时你无法预测 subscribe() 将会在什么线程执行。     * 而与 Subscriber.onStart() 相对应的,有一个方法 Observable.doOnSubscribe() 。     * 它和 Subscriber.onStart() 同样是在 subscribe() 调用后而且在事件发送前执行,但区别在于它可以指定线程。     * 默认情况下, doOnSubscribe() 执行在 subscribe() 发生的线程;而如果在 doOnSubscribe() 之后有 subscribeOn() 的话,它将执行在离它最近的 subscribeOn() 所指定的线程。     */    private void doOnSubscribe(){        Observable.create(new Observable.OnSubscribe<String>() {            @Override            public void call(Subscriber<? super String> subscriber) {            }        })                .subscribeOn(Schedulers.io())                .doOnSubscribe(new Action0() {                    @Override                    public void call() {                        //TODO 转菊花                        // 需要在主线程执行                    }                })                .subscribeOn(AndroidSchedulers.mainThread()) // 指定主线程(指定doOnSubscribe中逻辑在哪个线程执行)                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Observer<String>() {                    @Override                    public void onCompleted() {                    }                    @Override                    public void onError(Throwable e) {                    }                    @Override                    public void onNext(String s) {                    }                });    }

四、Map、FlatMap、Compose转换的使用

所谓变换,就是将事件序列中的对象或整个序列进行加工处理,转换成不同的事件或事件序列。
说白了就是针对事件序列的处理和再发送
原理:通过事件拦截和处理实现事件序列的变换。

  • 1、Map的使用
 /**     * map:一对一的转化     *      * map() 方法将参数中的 String 对象转换成一个 Bitmap 对象后返回,而在经过 map() 方法后,     * 事件的参数类型也由 String 转为了 Bitmap。(String和Bitmap只是举例子,实际中可以自己决定)     */    private void transformMap() {        //Func类包装的是又返回值的方法        Observable.just("http://q.qlogo.cn/qqapp/1105900198/8648E396207223FD4B9982F7E772D3A9/100")                .map(new Func1<String, Bitmap>() {// 输入类型 String                    @Override                    public Bitmap call(String path) {// 参数类型 String                        try {                            URL url = new URL(path);                            HttpURLConnection connection = (HttpURLConnection) url.openConnection();                            if (connection.getResponseCode() == 200) {                                return BitmapFactory.decodeStream(connection.getInputStream());// 返回类型 Bitmap                            }                        } catch (MalformedURLException e) {                            e.printStackTrace();                        } catch (IOException e) {                            e.printStackTrace();                        }                        return null;                    }                }).subscribeOn(Schedulers.newThread())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Action1<Bitmap>() {                    @Override                    public void call(Bitmap bitmap) {// 参数类型 Bitmap                        mImageView.setImageBitmap(bitmap);                    }                });    }
  • 2、FlatMap的使用
/**     * flatMap() 和 map() 有一个相同点:它也是把传入的参数转化之后返回另一个对象。     * 但需要注意,和 map() 不同的是, flatMap() 中返回的是个 Observable 对象,     * 并且这个 Observable 对象并不是被直接发送到了 Subscriber 的回调方法中。     *      * flatMap() 的原理是这样的:     * 1. 使用传入的事件对象创建一个 Observable 对象;     * 2. 并不发送这个 Observable, 而是将它激活,于是它开始发送事件;     * 3. 每一个创建出来的 Observable 发送的事件,都被汇入同一个 Observable ,而这个 Observable 负责将这些事件统一交给 Subscriber 的回调方法。     */    private void transformFlatMap() {        List<Student> students = new ArrayList<>();        for (int j = 0; j < 3; j++) {            Student student = new Student();            student.setName("王五");            List<Course> courses = new ArrayList<>();            for (int i = 0; i < 3; i++) {                Course course = new Course();                course.setCourseName("课程" + i);                courses.add(course);            }            student.setCourses(courses);            students.add(student);        }        Observable.from(students).flatMap(new Func1<Student, Observable<Course>>() {            @Override            public Observable<Course> call(Student student) {                return Observable.from(student.getCourses());            }        }).subscribe(new Action1<Course>() {            @Override            public void call(Course course) {                Log.e("---------->", "course_name:" + course.getCourseName());            }        });    }
//学生类    class Student {        private String name;        private List<Course> courses;        public String getName() {            return name;        }        public void setName(String name) {            this.name = name;        }        public List<Course> getCourses() {            return courses;        }        public void setCourses(List<Course> courses) {            this.courses = courses;        }    }
//课程类    class Course {        private String courseName;        public String getCourseName() {            return courseName;        }        public void setCourseName(String courseName) {            this.courseName = courseName;        }    }

这里写图片描述

注意:call方法执行了9次,因为有3个学生,每个学生有3门课,所以是9次,不是一次哦。

  • 3、Compose的使用
/**     * compose和Transformer,自定义Transformer实现Observable.Transformer接口,     * 就相当于一个方法,将功能封装好,每次调用方法就可以,这里只不过是把方法封在了compose中。     *      * 举例子:加入你要一个大萝卜,然后生产大萝卜的过程被封装在Transformer中,相当于一个人,然后每次你要萝卜的时候就用compose的方法,然后找到Transformer这个人就可以得到大萝卜了。     *     * Transformer实质上就是一个Func1<Observable<T>, Observable<R>>,就是将一个类型转换为另一个类型     */    public void transformCompose() {        Observable.just("111", "2222")                .compose(new DefaultTransformer<String>())                .subscribe(new Subscriber<List<String>>() {                    @Override                    public void onCompleted() {                    }                    @Override                    public void onError(Throwable e) {                    }                    @Override                    public void onNext(List<String> strings) {                        Log.e("------------->", "strings" + strings.size());                        for (int i = 0; i < strings.size(); i++) {                            Log.e("------------>", "element:" + strings.get(i));                        }                    }                });    }
public class DefaultTransformer<T> implements Observable.Transformer<T,List<T>> {    @Override    public Observable<List<T>> call(Observable<T> tObservable) {        return tObservable.subscribeOn(Schedulers.io()).map(new Func1<T, List<T>>() {            @Override            public List<T> call(T t) {                List<T> list = new ArrayList<T>();                list.add(t);                return list;            }        });    }}

我这里把字符串转为字符串列表了,感觉没多大用哈,就是举例子嘿嘿。

原创粉丝点击