【Rxjava】通俗说Rxjava

如下为Rxjava最基础也是最常见的使用样例:

        /**
         * 最基础的使用
         */
        Observable.create(new OnSubscribe<String>() {

            @Override
            public void call(Subscriber<? super String> arg0) {
                arg0.onNext("Hi");
                arg0.onNext("I'm xiaoming");
                arg0.onCompleted();
            }
        }).subscribe(new Subscriber() {

            @Override
            public void onCompleted() {
                Utils.p("结束了!");
            }

            @Override
            public void onError(Throwable arg0) {
                Utils.p("出错了!");
            }

            @Override
            public void onNext(Object arg0) {
                Utils.p((String) arg0);
            }
        });
  • 如果不在意onError,onFinish的通知,那么subscribe中的Subscriber完全可以直接使用Action1来代替

很典型的观察者模式,Rxjava取名也是名副其实,我来用图来理一下他们的关系。

这里写图片描述

onError 和 onComplete

与传统观察者模式不同, RxJava 的事件回调方法除了普通事件 onNext() (相当于 onClick() / onEvent())之外,还定义了两个特殊的事件:onCompleted() 和 onError()。

  • onCompleted(): 事件队列完结。RxJava 不仅把每个事件单独处理,还会把它们看做一个队列。RxJava 规定,当不会再有新的 onNext() 发出时,需要触发 onCompleted() 方法作为标志。
  • onError(): 事件队列异常。在事件处理过程中出异常时,onError() 会被触发,同时队列自动终止,不允许再有事件发出。
  • 在一个正确运行的事件序列中, onCompleted() 和 onError() 有且只有一个,并且是事件序列中的最后一个。需要注意的是,onCompleted() 和 onError() 二者也是互斥的,即在队列中调用了其中一个,就不应该再调用另一个。

ActionX, FuncX

  • X所代表的数字,表示其包装的call方法里会带有多少参数。
  • Func包装的是有返回值的方法,Action则无。

Observer 和 Subscriber

不仅基本使用方式一样,实质上,在 RxJava 的 subscribe 过程中,Observer 也总是会先被转换成一个 Subscriber 再使用。所以如果你只想使用基本功能,选择 Observer 和 Subscriber 是完全一样的。它们的区别对于使用者来说主要有两点:

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

defer

defer翻译过来有延迟,推迟之意
defer 和 just,from,create一样,都是产生Observable,但区别在于defer是在有订阅者订阅时才会创建observable, 而只有在创建时 ,defer才会取用数据,这也保证了它的状态数据都是最新的。
见例子:

a = 10;
Observable<String> o1 = Observable.just("just result: " + a);
Observable<String> o2 = 
    Observable.defer(new Func0<Observable<String>>() {
    @Override
    public Observable<String> call() {
        return Observable.just("defer result: " + a);
    }
});
a = 12;
o1.subscribe(new Action1<String>() {

    @Override
    public void call(String t) {
        System.out.println(t);
    }
});
o2.subscribe(new Action1<String>() {

    @Override
    public void call(String t) {
        System.out.println(t);
    }
});


输出为:

"just result: 10"
"defer result: 12"

Map,FlatMap ——变换

根据应用场景来更容易消化知识,这次我们来到校园,有这么些学生。

Student s1 = new Student(110, "王小虎", 15, new ArrayList<Course>() {
            {
                add(new Course("物理"));
                add(new Course("化学"));
            }
        });

Student s2 = new Student(111, "李刚", 17, new ArrayList<Course>() {
            {
                add(new Course("政治"));
                add(new Course("语文"));
            }
        });

Student s3 = new Student(112, "李文龙", 16, new ArrayList<Course>() {
            {
                add(new Course("美术"));
                add(new Course("武术"));
            }
        });

故事场景1——Map

需要通过遍历每个学生找到各自的班主任老师,并打印出老师的名字来。

        /**
         * 为每个学生来找到他们的老师并打印出名字来 Map
         */
        Observable.just(s1, s2, s3).map(new Func1<Student, Teacher>() {

            @Override
            public Teacher call(Student student) {
                Utils.p(student.name + "的老师是:");
                return findTeacherBy(student);
            }
        }).subscribe(new Subscriber<Teacher>() {

            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable arg0) {

            }

            @Override
            public void onNext(Teacher teacher) {
                Utils.p(teacher.name);
            }
        });


public static Teacher findTeacherBy(Student student) {
        Teacher teacher = null;
        switch (student.id) {
        case 110:
            teacher = new Teacher("李老师");
            break;
        case 111:
            teacher = new Teacher("张老师");

            break;
        case 112:
            teacher = new Teacher("曹老师");
            break;
        default:
            break;
        }
        return teacher;
    }

打印输出为:

王小虎的老师是:
李老师
李刚的老师是:
张老师
李文龙的老师是:
曹老师

这里写图片描述

故事场景2——FlatMap

需要拿到每个学生他所学习的课程,并打印出课程名称来。
有两种方式来实现。

// 方案1:拿到每个学生后,遍历该学生的课程列表并打印
        Observable.just(s1, s2, s3).subscribe(new Action1<Student>() {

            @Override
            public void call(Student arg0) {
                for (Course course : arg0.courses) {
                    Utils.p(arg0.name + "  " + course.courseName);
                }
            }
        });
// 方案2:使用flatMap,不用自己遍历
        Observable<Student> studentObservable = Observable.just(s1, s2, s3);
        Observable<Course> courseObservable = studentObservable.flatMap(new Func1<Student, Observable<Course>>() {

            @Override
            public Observable<Course> call(Student arg0) {
                Utils.p(arg0.name);
                return Observable.from(arg0.courses);
            }
        });

        courseObservable.subscribe(new Subscriber<Course>() {

            @Override
            public void onCompleted() {
                Utils.p("发射结束");
            }

            @Override
            public void onError(Throwable arg0) {

            }

            @Override
            public void onNext(Course arg0) {
                Utils.p("  " + arg0.courseName);
            }
        });

结果输出为:

王小虎
  物理
  化学
李刚
  政治
  语文
李文龙
  美术
  武术
发射结束

这里写图片描述

Map vs FlatMap

  • Map输入到输出是 1v1的, 而FlatMap的输入到输出则是1vN的,所以你也能理解到为什么叫做flatMap了,flat 是扩展的意思。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值