RxJava(新手推荐二)

在上一部分RxJava(新手推荐一),我带大家了解了RxJava的基本结构以及介绍了map()操作符。第二部分,我打算给大家介绍Observable的几种创建方式以及其他一些操作符。在这一部分,我打算去掉Lamads表达式,虽然简洁但是可读性感觉并不好(其实我自己不会,不要拆穿啊)。

Observable(被观察者)的创建方式

1. create

Observable.create(new Observable.OnSubscribe<String>() {
       @Override
       public void call(Subscriber<? super String> subscriber) {
           subscriber.onNext("hello world1");
           subscriber.onCompleted();
       }
   });

2. just

假如没有just的创建方式,我们现在要发出多个事件,我们该怎么写呢?

Observable.create(new Observable.OnSubscribe<String>() {
       @Override
       public void call(Subscriber<? super String> subscriber) {
           subscriber.onNext("hello world1");
           subscriber.onNext("hello world2");
           subscriber.onNext("hello world3");
           subscriber.onCompleted();
       }
   }).subscribe(subscriber);

而有了Just的方式后,我们就可以这么做:

Observable.just("hello world1","hello world2","hello world3").subscribe(subscriber);

3. from

 String[] hello = {"hello world1",
"hello world2","hello world3"};
Observable.from(hello).subscribe(subscriber);

…其他创建方式

常用操作符(介绍几个常用的,入门后其他的可以自己去看)

map:

在发出事件后,对Observable发出的进行处理,是一对一处理,进去一个,然后经过处理,得到一个对应的结果。

String[] hello = {"hello world1","hello world2","hello world3"};
Observable.from(hello).map(new Func1<String, String>() {
    @Override
    public String call(String s) {
        return s+" myscrate";
    }
}).subscribe(subscriber);

filter:

顾名思义,就是过滤器的意思。我们不能将所有传出的事件一股脑给SubScriber,而是将满足条件的传出去即可。多说无益,看例子:

假设现在有个Student类:

class Student {

        private int age;
        private String name;

        public Student(){}
        public Student(int age,String name){
            this.name = name;
            this.age = age;
        }
    }

里面有姓名和年龄字段。我们的需求是挑出其中年龄大于20的学生,假设就是女生吧,岂不美哉。那么我们怎么做呢?

先准备三个学生:

 Student stu1 = new Student(18,"nana");
Student stu2 = new Student(21,"xiaoli");
Student stu3 = new Student(25,"lixinyu");

指定Subscribe的动作(先展示出来供翻牌):

Action1<Student> studentNextAction1 = new Action1<Student>() {
        @Override
        public void call(Student student) {

            System.out.println(student.name+" > 20岁 ");
        }
    };

最后一步,创建Observable并订阅studentNextAction1。

Observable.just(stu1,stu2,stu3).filter(new Func1<Student, Boolean>() {
        @Override
        public Boolean call(Student student) {
            return student.age > 20 ? true : false;
        }
    }).subscribe(studentNextAction1);

仔细看中间的处理过程,我们在filter中将年龄大于20岁的返回true,可以传出到subscribe(观察者)中。
那么结果如何呢?

//Output


I/System.out: xiaoli > 20岁

I/System.out: lixinyu > 20岁


目的达到。

flatMap:

先不说这个操作符有什么用,来看个例子就懂了。每个学生有好多门课,每门课都有对应的成绩和课程名称。

class Course{

        private String courseName; //课程名称
        private int grade; // 成绩

        public Course(){}
        public Course(String courseName,int grade){
            this.courseName = courseName;
            this.grade = grade;
        }
    }

那么我们的学生类对应就变成如下的:

class Student {

     private int age;
     private String name;
     private Course[] courses;

     public Student(){}
     public Student(int age,String name,Course[] courses){
         this.name = name;
         this.age = age;
         this.courses = courses;
     }
 }

现在需求来了,将所有学生考试不及格的科目列出来。
是你你会怎么做?

你可能会这么做

 Course[] stu1Courses = {new Course("算法导论",78),new Course("计算机网络",59),new Course("操作系统",89)};
Course[] stu2Courses = {new Course("算法导论",21),new Course("计算机网络",76),new Course("操作系统",87)};
Course[] stu3Courses = {new Course("算法导论",78),new Course("计算机网络",54),new Course("操作系统",62)};
Student stu1 = new Student(18,"nana",stu1Courses);
Student stu2 = new Student(21,"xiaoli",stu2Courses);
Student stu3 = new Student(25,"lixinyu",stu3Courses);
Student[] students = {stu1,stu2,stu3};

Action1<Student> courseNextAction1 = new Action1<Student>() {
    @Override
    public void call(Student stu) {
        Course[] courses = stu.courses;
        for(int i=0;i<courses.length;i++){

            if(courses[i].grade < 60){
                System.out.println(stu.name+courses[i].courseName+courses[i].grade);
            }
        }

    }
};

最后一步,完成订阅。

Observable.from(students).subscribe(courseNextAction1);

这么写会不会有什么问题?我们可以看到在courseNextAction1做了太多工作,没传出来一个Student都会执行一遍循环。那么有没有简单点的写法呢?

    //(1)准备订阅者
   Action1<Course> courseNextAction = new Action1<Course>() {
       @Override
       public void call(Course course) {

           if(course.grade < 60){
               System.out.println(course.courseName+":"+course.grade);
           }
       }
   };

//(2)创建Observable并订阅
 Observable.from(students).flatMap(new Func1<Student, Observable<? extends Course>>() {
        @Override
        public Observable<? extends Course> call(Student student) {
            return Observable.from(student.courses);
        }
    }).subscribe(courseNextAction);

我们分析下上面的写法,我们首先创建Observable(被观察者),随后经过flatMap变换。过程如下

flatMap流程

Output


计算机网络:59

算法导论:21

计算机网络:54


….

这一部分主要讲了一些常用的操作符以及Observable的几种不同的创建方式。在下一部分中我将将RxJava中的Schedule以及在使用RxJava的注意事项,包括如何避免内存泄漏等。

参考文章:

给 Android 开发者的 RxJava 详解