RxJava学习

来源:互联网 发布:ubuntu 命令行 deb 编辑:程序博客网 时间:2024/05/18 05:01

1、首先学习rxJava必须理清楚什么是观察者,什么是被观察者?谁被谁观察?

其实是“观察者”观察“被观察者”,被观察者有什么动作会通知“观察者”,告诉他自己将要干嘛。

观察者:Observser(Subscriber)

        被观察者:Observable  


被观察者的创建方式,不算方法重载的话我记得好像有13种还是19种,我目前也只熟悉几种:

最基本的一种创建观察者方式:

  /**         * 创建被观察者方法(1):create(最基本)         */        Observable observable = Observable.create(new Observable.OnSubscribe<String>() {            @Override            public void call(Subscriber<? super String> subscriber) {                subscriber.onNext("Hello");                subscriber.onNext("RxJave");                subscriber.onCompleted();            }        });
以下是其他方式创建被观察者:

 /**         * 创建被观察者方法(2):just(快捷,将传入的参数一次发送出来)         * just里面的相当于都是调用         * onNext("Hello");         * onNext("RxJava2");         * onCompleted();         */        Observable observable1 = Observable.just("Hello", "RxJava2");        /**         * 创建被观察者方式3:from(T[])(传入一个数组拆分成具体对象后依次发送出来)         * onNext("Hello");         * onNext("RxJava3");         * onCompleted();         */        String[] words = {"Hello", "RxJava3"};        Observable observable2 = Observable.from(words);        /**         * 也可以把Observer拆成三个Action单独来订阅         */        /**         * Action1是RxJava的一个接口,有入参无出参         */        Action1<String> onNextAction = new Action1<String>() {            @Override            public void call(String s) {                Log.i("MainActivity", s);            }        };        Action1<Throwable> onErrorAction = new Action1<Throwable>() {            @Override            public void call(Throwable throwable) {            }        };        /**         * Action是RxJava的一个接口,无入参无出参,刚好适合onCompleted         */        Action0 onCompletedAction = new Action0() {            @Override            public void call() {                Log.i("MainActivity", "onCompleted");            }        };        observable.subscribe(onNextAction);        observable.subscribe(onErrorAction, onErrorAction);        observable.subscribe(onNextAction, onErrorAction, onCompletedAction);


一个基本的Observer会实现三个方法,当然也可以只实现一个方法,如下:

 /**         * onError和onCompleted只会走一个         */        Observer<String> observer = new Observer<String>() {            @Override            public void onCompleted() {                //当事件队列执行完成的时候会走这个方法            }            @Override            public void onError(Throwable e) {                //当执行时间队列的过程中出错会走这个方法并终止            }            @Override            public void onNext(String s) {                //执行事件队列            }        };
**         * Subscriber是Observer接口的实现类,跟Observer的基本使用方式完成一样;         * 实质上,rxJava在subscribe的过程中,Observer会先被转换成一个Subscriber再使用,所以如果         * 只是想使用基本功能,选择哪一个都一样;         *         * Subscriber与Observer的主要区别:         *      (1)Subscriber新增了onStart()方法,这个方法在onNext之前执行,做一些准备工作;         *      (2)Subscriber实现了另一个接口Subscription的方法unSubscribe(),是用来取消订阅的,当这个         *           方法被调用之后Subscriber就不再接收事件。当然取消订阅之前调用isUnsubscribed()         *           先判断一下订阅状态。这个方法很重要,在Subscriber不想再收Obserable传递过来的         *          事件的时候,记得取消订阅,防止内存泄露发生。         */        Subscriber<String> subscriber = new Subscriber<String>() {            @Override            public void onCompleted() {                Log.i("MainActivity", "onCompleted");            }            @Override            public void onError(Throwable e) {            }            @Override            public void onNext(String s) {                Log.i("MainActivity", s);            }        };

Observable被Observer(Subscriber)订阅:

 observable2.subscribe(subscriber);

 //场景1:打印数组        Observable.from(new String[]{"cy", "yl"})                .subscribe(new Action1<String>() {                    @Override                    public void call(String s) {                        Log.i("MainActivity", s);                    }                });

rxJava很吊的原因之一就是操作符:

下面介绍一些操作符及使用场景和实例代码:


操作符之Scheduler(调度器)

 /**         * Schedulers 是RxJava提供的调度器,         * AndroidSchedulers是rxJava提供的android专用的调度器         * .subscribeOn指定之前的操作在哪个线程中执行         * .observerOn指定之后的操作在哪个线程中执行         *         * SchedulersAPI:         *   (1)Schedulers.immediate()直接在当前线程运行,相当于不指定线程         *   (2)Schedulers.newThread()总是开启新线程,并且在新线程中运行         *   (3)Schedulers.io()耗时操作就使用这个scheduler,内部是一个可复用的无上限的线程池         *   (4)Schedulers.computation()专门用来做大计算的sheduler,可开线程数与cpu核数相同         *   (5)AndroidSchedulers.mainThread()指定操作将在主线程中执行         */        Observable.just(1, 2, 3, 4)                .subscribeOn(Schedulers.io())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Action1<Integer>() {                    @Override                    public void call(Integer integer) {                        Log.i("MainActivity", integer + "");                    }                });
其他操作符:

  /**         * Func1是RxJava的一个接口,有入参无出参         * 变换操作符:         *   .map()事件对象的直接变换(1对1变换,无法返回一个新的Obsrvable)         *   .flatMap()时间对象的1对多转换,可以返回一个新的Observable,可以解决循环问题(尽可能的让subscriber的操作简单化),可以用来解决嵌套请求更简单         *   .concatMap()用法跟flatMap()一样,但是他有序的,flatMap是无序的。能够保证事件流保持原来的序列         *   .take(4) 只取事件队列的前四个         *   .taskLast(4)只去事件队列的后四个         *   .distinct()过滤事件流重复发射事件         *   .distinctUntilChange()过滤一样的事件直到时间发生编号才进行发射         *   .repeat()按照事件队列顺序重复发射事件         *   .first()只发射事件队列中第一个事件         *   .last()只发射事件队列中最后一个事件         *   .shkipLst(3)跳过事件队列后三个,意思就是最后三个事件不发射         *   .timeout(2,TimeUnit.SECONDS)在规定时间内发射事件队列,如果总体用时超过2秒,没有发送的事件将不再发送         *   .sample(2,TimeUnit.SECONDS)发射指定时间内事件流中的最后一个事件         *   .throttleFirst()发射指定时间内事件流中的第一个事件         *   .debounce(2,TimeUnit.SECONDS)在计时时间内事件流没有产生新事件则发送当前事件,若有新事件则重新计时         *   .groupBy()根据自定义规则对事件流进行分类         *   .buffer(3)将输入的事件队列,按照输入值进行分组,这个输入的是三,那么三个一组         *   .doOnNext允许在输出之前,用输出的数据做其他额外的事情。但是不能阻挡数据.doOnNext(title -> saveTitle(title))         */        //map场景:就是把String对象转换成了Bitmap对象再输出        Observable.just("storage/emulated/0/Pictures/IMG_20170529_213655.jpg")                .map(new Func1<String, Bitmap>() {                    @Override                    public Bitmap call(String s) {                        //下面的PicUtils.lessenUriImage是根据图片路径拿到图片的方法                        return PicUtils.lessenUriImage(s);                    }                })                .subscribe(new Action1<Bitmap>() {                    @Override                    public void call(Bitmap bitmap) {                        setBitmaoToIv(bitmap);                    }                });        //flatMao场景1:假设输入一个学生数组,需要输出每个学生的课程名,学生的课程是多个的,        // 解决办法1:可以用.from输入学生数组再拿到每个学生,根据学生遍历他的课程集合输出        List<Student> students = new ArrayList<>();        Observable.from(students)                .subscribe(new Action1<Student>() {                    @Override                    public void call(Student student) {                        List<Course> courses = student.getCourses();                        for (Course course : courses) {                            Log.i("MainActivity", course.getCourseName());                        }                    }                });        //解决办法2:如果不想再subscriber里面做循环,那么就这样处理        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.i("MainActivity", course.getCourseName());                    }                });        //利用.from的原理(把入参一个一个输出),然后把Student的courses当做一个新的Obsevable输出        //flatMap场景2:嵌套请求,我先上传一张图片再立马把这张图片下载下来展示        viewModel.upload(countingRequestBody)                .flatMap(new Func1<UploadResponse, Observable<ResponseBody>>() {                    @Override                    public Observable<ResponseBody> call(UploadResponse uploadResponse) {                        return viewModel.downPic(uploadResponse.file);                    }                })                .subscribe(new Action1<ResponseBody>() {                    @Override                    public void call(ResponseBody responseBody) {                        Bitmap bitmap = BitmapFactory.decodeStream(responseBody.byteStream());                    }                });        //上面这个代码可以用lambda简化如下:        viewModel.upload(countingRequestBody)                .flatMap(uploadResponse -> viewModel.downPic(uploadResponse.file))                .subscribe(responseBody -> BitmapFactory.decodeStream(responseBody.byteStream()), e -> Log.i("MainActivity", e.getMessage()));        RxView.clicks(findViewById(R.id.bt))                .throttleFirst(500, TimeUnit.MILLISECONDS)                .subscribe(new Action1<Void>() {                    @Override                    public void call(Void aVoid) {                        Log.i("RxBinding", "点了");                    }                });        Observable.just("1", "2", "3", "4", "5")                .take(3)                .subscribe(new Action1<String>() {                    @Override                    public void call(String s) {                        Log.i("Take", s);                    }                });        Observable.just("1", "1", "1", "2", "3", "3", "4")                .distinct()                .subscribe(new Action1<String>() {                    @Override                    public void call(String s) {                        Log.i("distinct", s);                    }                });                Observable.just("1", "2", "3")                .repeat()                .subscribe(new Action1<String>() {                    @Override                    public void call(String s) {                        Log.i("repeat", s);                    }                });                Observable.just(1, 2, 3, 4, 5, 6, 7)                .groupBy(new Func1<Integer, Boolean>() {                    @Override                    public Boolean call(Integer integer) {                        return integer % 2 == 0;                    }                })                .subscribe(new Action1<GroupedObservable<Boolean, Integer>>() {                    @Override                    public void call(GroupedObservable<Boolean, Integer> booleanIntegerGroupedObservable) {                        if (booleanIntegerGroupedObservable.getKey()) {                            //输出的是能整除2的                        } else {                            //输出的是不能整除2的                        }                    }                });
当然操作符远远不止这些。我只是做一些举例。


原创粉丝点击