RxJava事件流变换者--操作符

对于Rxjava来说,操作符是它的一个非常重要的概念,如官网:

而上节上也贴了一下都有哪些操作符,其实还不少,所以有必要仔细学习一下关于操作符这块的东东,那操作符在Rxjava中扮演着什么样的角色呢,下面用一个形象的举例来说明:

在Rxjava中,如果把整个事件流看作是工厂的流水线,Observable就是原料,Observer就是我们的产品经理,这个产品是怎么交到我们的产品经理呢?中间很重要的就是工人,也就是Operator(操作符),它负责在Observable发出的事件和Observable的响应之间做一些处理

光说不练假把式,下面用代码用上几个操作符先来感受【具体细节之后会慢慢去学】下Rxjava中的操作符强大之处,具体的操作符会在未来仔细去学,这里先初步有个印象既可。

场景一:根据某个学生的信息,获取他所在的班级的所有学生

还是按照上一次的流程来:

①、创建被观察者Observable

②、创建观察者Observer

/**
 * 场景:根据某个学生的信息,获取他所在的班级的所有学生
 */
public class RxJavaOperator {

    @SuppressWarnings("serial")
    static List<Student> students = new ArrayList<Student>() {
        {
            add(new Student("张三", 29));
            add(new Student("李四", 23));
            add(new Student("王五", 25));
        }
    };

    static Observable<Student> query(String name, int age) {
        Student student = new Student(name, age);
        return Observable.just(student);
    }

    public static void main(String[] args) {
        testOperator();
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static void testOperator() {
        // 创建被观察者Observable
        Observable studentObservable = query("李四", 23);

        // 创建观察者Observer
        Observer<Student> observer = new Observer<Student>() {

            @Override
            public void onCompleted() {
                System.out.println("onCompleted()");
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Student t) {
                System.out.println("onNext() value = " + t);
            }
        };
    }

}

③、被观察者订阅(subscribe)观察者

/**
 * 场景:根据某个学生的信息,获取他所在的班级的所有学生
 */
public class RxJavaOperator {

    @SuppressWarnings("serial")
    static List<Student> students = new ArrayList<Student>() {
        {
            add(new Student("张三", 29));
            add(new Student("李四", 23));
            add(new Student("王五", 25));
        }
    };

    static Observable<Student> query(String name, int age) {
        Student student = new Student(name, age);
        return Observable.just(student);
    }

    static Observable<Student> getAllStudents(Student student) {
        return Observable.from(students);//这里采用了from操作符
    }

    public static void main(String[] args) {
        testOperator();
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static void testOperator() {
        // 创建被观察者Observable
        Observable studentObservable = query("李四", 23);

        // 创建观察者Observer
        Observer<Student> observer = new Observer<Student>() {

            @Override
            public void onCompleted() {
                System.out.println("onCompleted()");
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Student t) {
                System.out.println("onNext() value = " + t);
            }
        };

        // 被观察者订阅(subscribe)观察者
        studentObservable.flatMap(new Func1<Student, Observable<Student>>() {//这里采用了flatMap操作符

            @Override
            public Observable<Student> call(Student student) {
                return getAllStudents(student);
            }
        }).subscribe(observer);
    }

}

编译运行:

上面感受一下就行,不用纠结太多细节,其中用到了just、from、flatMap、subscribe操作符,这些常用操作符之后会再细细学~

场景二:找出Sdcard上所有".png"格式的文件

这里将开发工具切到android studio上来,新建一个工程,并添加Rxjava的依赖:

基于场景一的代码对其进行扩展,首先先获得sdcard的根据目录文件:

然后还是按照标准的步骤去写:

①、创建被观察者Observable

这里为了获得满足条件的文件名称,用到了多个操作符来达到目的,体会下:

②、创建观察者Observer

③、被观察者订阅(subscribe)观察者

private void searchFiles() {
        String basePath = Environment.getExternalStorageDirectory().getPath();
        File rootFile = new File(basePath);
        // 创建被观察者Observable
        Observable observable = Observable.just(rootFile)
                .flatMap(new Func1<File, Observable<File>>() {//进行遍历
                    @Override
                    public Observable<File> call(File file) {
                        return listFiles(file);
                    }
                })
                .filter(new Func1<File, Boolean>() {//这时会对文件进行一一判断过滤
                    @Override
                    public Boolean call(File file) {
                        Log.e("cexo", "filter() file = " + file.getName());
                        return file.getName().endsWith(".png");
                    }
                })
                .map(new Func1<File, String>() {//最后如果条件满足的文件则会传到这,最后返回文件名
                    @Override
                    public String call(File file) {
                        return file.getName();
                    }
                });

        // 创建观察者Observer
        Observer<String> observer = new Observer<String>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String s) {
                Log.e("cexo", "onNext() s = " + s);
            }
        };

        // 被观察者订阅(subscribe)观察者
        observable.subscribe(observer);
    }

编译运行:

下面在sdcard上放入几张png图片文件,然后再运行:

但是由于现实sdcard可能png的图片非常多,如果每发现一个就打印出来貌似不太好,有木有过滤到之后放到一个集合当中,最终一次性输出出来呢?当然有,那就再次体现Rxjava操作符强大之处的时机来了,修改代码如下:

但是!!!目前输出还是一个个输出的,这里还需要观察者的泛形数据类型,那需要改成啥呢?先看一下toList()操作符的源码返回的是:

所以修改观察者的泛形数据类型为:

private void searchFiles() {
        String basePath = Environment.getExternalStorageDirectory().getPath();
        File rootFile = new File(basePath);
        // 创建被观察者Observable
        Observable observable = Observable.just(rootFile)
                .flatMap(new Func1<File, Observable<File>>() {//进行遍历
                    @Override
                    public Observable<File> call(File file) {
                        return listFiles(file);
                    }
                })
                .filter(new Func1<File, Boolean>() {//这时会对文件进行一一判断过滤
                    @Override
                    public Boolean call(File file) {
                        Log.e("cexo", "filter() file = " + file.getName());
                        return file.getName().endsWith(".png");
                    }
                })
                .map(new Func1<File, String>() {//最后如果条件满足的文件则会传到这,最后返回文件名
                    @Override
                    public String call(File file) {
                        return file.getName();
                    }
                })
                .toList();

        // 创建观察者Observer
        Observer<List<String>> observer = new Observer<List<String>>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(List<String> list) {
                Log.e("cexo", "onNext() s = " + list);
            }
        };

        // 被观察者订阅(subscribe)观察者
        observable.subscribe(observer);
    }

编译运行:

最后对于Rxjava的实现还可以简化一下,看起来更加链式,更加舒服,如下:

可能这时大家会想到,那这个方法得在异步去执行吧,当执行完成之后的数据应该得在ui线程中去进行显示处理,那这个在哪里体现呢?当然是在后面会学习到的,会有专门的线程控制,慢慢学!!

对于这篇写的代码欣赏欣赏既可,可能看着还是一头雾水,这是因为还木有仔细去学习这些细节,这里主要是展示rxjava的操作符的魅力所在,能感受到那就目的达到了,具体细节之后再慢慢学!

原文地址:https://www.cnblogs.com/webor2006/p/7526413.html