RxAndroid菜鸟必入

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

一、基本概念和添加依赖:

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

1Schedulers.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:一对一的转化
     * <p>
     * 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 的回调方法中。
     * <p>
     * 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中。
     * <p>
     * 举例子:加入你要一个大萝卜,然后生产大萝卜的过程被封装在Transformer中,相当于一个人,然后每次你要萝卜的时候就用compose的方法,然后找到Transformer这个人就可以得到大萝卜了。
     * <p>
     * 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;
            }
        });
    }
}

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


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值