• 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的操作符的魅力所在,能感受到那就目的达到了,具体细节之后再慢慢学!

  • 相关阅读:
    [LeetCode] 771. Jewels and Stones
    [LeetCode] 129. Sum Root to Leaf Numbers
    java定时器demo
    Spring Boot与监控管理
    springboot与热部署
    springboot中的web项目不能访问templates中的静态资源
    @Component 和 @Bean 的区别
    springcluoud入门
    Dubbo和Zookerper的关系
    Spring boot配置Dubbo三种方式
  • 原文地址:https://www.cnblogs.com/webor2006/p/7526413.html
Copyright © 2020-2023  润新知