RxJava学习总结


1. RxJava主要作用

1.1 线程切换

实现了Android中Handler和AsyncTask的功能

1.2 链式编程、响应式编程

  • 逻辑简介
  • 实现优雅
  • 帮助处理复杂的业务逻辑

即使遇到非常复杂的业务逻辑及线程间切换,也能保证代码的可阅读性


2. RxJava思想总结

2.1 什么是ReactiveX

微软给的定义是,Rx是一个函数库,让开发者可以利用可观察序列和LINQ风格查询操作符来编写异步和基于事件的程序,使用Rx,开发者可以用Observables表示异步数据流,用LINQ操作符查询异步数据流, 用Schedulers参数化异步数据流的并发处理,Rx可以这样定义:Rx = Observables + LINQ + Schedulers。

ReactiveX.io给的定义是,Rx是一个使用可观察数据流进行异步编程的编程接口,ReactiveX结合了观察者模式、迭代器模式和函数式编程的精华。

目前有许多语言都推出了Rx库 详情见 官网

2.2 与观察者模式思想的不同点

传统观察者模式有一个被观察者,通过轮询保存的观察者对象集合去调用接口通知到所有的观察者,属于一对多的关系。

典型的RxJava思想中,一般是一个被观察者对应一个观察者,属于一对一的关系。


3. RxJava如何实现线程切换

.subscribeOn(Schedulers.io())//被观察者执行线程
.observeOn(AndroidSchedulers.mainThread())//观察者执行线程

4. 各类操作符说明及简单用法

创建型操作符

create,just,fromArray,empty,range

Observable.create(new ObservableOnSubscribe<Object>() {
        @Override
        public void subscribe(ObservableEmitter<Object> emitter) throws Exception {
            emitter.onNext("发送数据");
        }
    }).subscribe(new Observer<Object>() {
        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onNext(Object o) {
            Log.i(TAG, "onNext: " + o);
        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
    });

变换型操作符

Map,flatMap,concatMap,groupBy,buffer

Observable.just("张三")
            .map(new Function<String, Boolean>() {
                @Override
                public Boolean apply(String name) throws Exception {
                    return name.equals("张三");
                }
            }).subscribe(new Observer<Boolean>() {
        @Override
        public void onSubscribe(Disposable d) {

        }

        @Override
        public void onNext(Boolean b) {
            Log.i(TAG, "onNext: " + b);
        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onComplete() {

        }
    });

过滤型操作符

filter,take,distint,elementAt

 	User user1 = new User("111", 1);
    User user2 = new User("333", 3);
    User user3 = new User("999", 9);
    User user4 = new User("222", 2);
    User user5 = new User("888", 8);
    User user6 = new User("777", 7);

    Observable.just(user1, user2, user3, user4, user5, user6)
            .filter(new Predicate<User>() {
                @Override
                public boolean test(User user) throws Exception {
                    return user.age > 4;
                }
            })
            .subscribe(new Consumer<User>() {
                @Override
                public void accept(User user) throws Exception {
                    System.out.println("user = [" + user + "]");
                }
            });

条件型操作符

all,any,contains,isEmpty

	User user1 = new User("111", 1);
    User user2 = new User("333", 3);
    User user3 = new User("999", 9);
    User user4 = new User("222", 2);
    User user5 = new User("888", 8);
    User user6 = new User("777", 7);

    List<User> users = new ArrayList<>();
    users.add(user1);
    users.add(user2);
    users.add(user3);
    users.add(user4);
    users.add(user5);
    users.add(user6);

    Observable.fromIterable(users)
//all条件操作符,类似于And(与)条件,上游发射的所有数据都会经过判断, 一个条件为false 最后结果就是false 全部为true,最后结果才会为true
//any操作符和all恰好相反,类似Or(或)条件 一个条件为true,结果为true,所有条件为false,结果为false
//contains 验证要发射的数据里面是否有包含 contains 里面的值,如果有则返回true
//如果发送的是一个empty,则下游接收的时候是ture,否则为false
            .all(new Predicate<User>() {
                @Override
                public boolean test(User user) throws Exception {
                    return "000".equals(user.name);
                }
            }).subscribe(new Consumer<Boolean>() {
        @Override
        public void accept(Boolean aBoolean) throws Exception {
            System.out.println("aBoolean = [" + aBoolean + "]");
        }
    });

合并型操作符

startWith,concatWith,merge,zip

//startWith:先发射 2和3,然后再通过startWith(1),最后输出 1, 2 3 .说明startWith中的内容先输出
//concatWith和startWith相反,先执行发射的数据,然后再发射concatWith里面的数据
//merge,合并多个操作符为一个数据源同时发送
//zip ,将上游所有的发射结果通过function处理以后统一返回给下游,比如一个页面需要调用多个接口才能渲染界面,则可以通过此方式处理,当数据全部得到以后再次渲染界面。不用等到一个接口完成以后再次调用另一个接口
 Observable.just(4)
            .startWith(3)
            .startWith(2)
            .startWith(1)
            .subscribe(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) throws Exception {
                    Log.i(TAG, "accept: "+integer);
                }
            });

输出结果:

I/MainActivity: accept: 1
I/MainActivity: accept: 2
I/MainActivity: accept: 3
I/MainActivity: accept: 4

异常型操作符

onErrorResumeNext,onErrorReturn,onExceptionResumeNext

/**
1. 都不能处理Error级别的错误,
2. 都能拦截到上游的异常
onErrorResumeNext 拦截发射的异常  ,能够处理 throw Exception级别的异常,能够接收异常消息,需要返回一个新的Observable,执行发送 ,不能处理 throw Error级别异常
onErrorReturn     拦截发射的异常,能够处理 throw Execption级别异常 ,能够接收异常消息,可以提供返回一个默认值,但是不能处理 throw Error级别异常
onExceptionResumeNext     拦截发射的异常,能够处理 throw Execption级别异常 不接受异常信息,获得Observer继续发送,同样不能处理 Error级别的异常
*/
Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> emitter) throws Exception {
            emitter.onNext("1");
            emitter.onNext("2");
            emitter.onNext("3");
            throw new RuntimeException("hahahhaa"); // 下游onErrorResumeNext 能够处理
	//                throw new IllegalAccessError("hahahhaa"); //下游onErrorResumeNext 不能处理

        }
    })
            .onErrorResumeNext(new Function<Throwable, ObservableSource<? extends String>>() {
                @Override
                public ObservableSource<? extends String> apply(Throwable throwable) throws Exception {
                    throwable.printStackTrace();
                    return Observable.create(new ObservableOnSubscribe<String>() {
                        @Override
                        public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                            emitter.onNext("4");
                            emitter.onNext("5");
                            emitter.onNext("6");
                        }
                    });
                }
            })
            .subscribe(new Observer<String>() {
                @Override
                public void onSubscribe(Disposable d) {

                }

                @Override
                public void onNext(String s) {
                    Log.i(TAG, "onNext: " + s);
                }

                @Override
                public void onError(Throwable e) {
                    Log.i(TAG, "onError: " + e);
                }

                @Override
                public void onComplete() {
                    Log.i(TAG, "onComplete: ");
                }
            });

5. 背压

背压

  • 背压针对的问题:当被观察者发送事件速度 > 观察者接收事件速度。被观察者 发送事件速度太快,而观察者 来不及接收所有事件,从而导致观察者无法及时响应 / 处理所有发送过来事件的问题,最终导致缓存区溢出、事件丢失 & OOM
  • 背压的作用:解决了 因被观察者发送事件速度 与 观察者接收事件速度 不匹配(一般是前者 快于 后者),从而导致观察者无法及时响应 / 处理所有 被观察者发送事件 的问题
  • 背压的使用
        // 步骤1:创建被观察者 =  Flowable
        Flowable.create(new FlowableOnSubscribe<Integer>() {
            @Override
            public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
                Log.d(TAG, "发送事件 1");
                emitter.onNext(1);
                Log.d(TAG, "发送事件 2");
                emitter.onNext(2);
                Log.d(TAG, "发送事件 3");
                emitter.onNext(3);
                Log.d(TAG, "发送完成");
                emitter.onComplete();
            }
        }, BackpressureStrategy.ERROR)
                .subscribe(new Subscriber<Integer>() {
                // 步骤2:创建观察者 =  Subscriber & 建立订阅关系

                    @Override
                    public void onSubscribe(Subscription s) {
                        Log.d(TAG, "onSubscribe");
                        s.request(3);
                    }

                    @Override
                    public void onNext(Integer integer) {
                        Log.d(TAG, "接收到了事件" + integer);
                    }

                    @Override
                    public void onError(Throwable t) {
                        Log.w(TAG, "onError: ", t);
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "onComplete");
                    }
                });

6.RxJava源码分析

如何实现链式代码调用

从ObservableOnSubscribe->map->subscribe流程分析源码实现过程
在这里插入图片描述

subscribe();执行时
关键代码:使用subscribeActual()
抽象方法subscribeActual的实现在ObservableMap中可以看到把被观察者对象通过装箱的形式传递
给了上层,也就是ObservableOnSubscribe的对象持有中,此时ObservableOnSubscribe就拥有
了两层箱子,第一层是map观察者,第二层是subscribe观察者。此时走onNext方法会进行拆箱操作,
先拆第一层箱子,执行递归处理不停onNext及拆箱。便实现了链式顺序调用

如何实现线程切换?

根据前面说的典型情况,加入.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())线程切换后。
在这里插入图片描述

ObservableSubscribeOn也是同样以subscribeActual装箱的形式加入到链式结构中但在其中加入了新建线程/使用线程池调用,
同理observeOn中切换到Android主线程中使用了Handler切换

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值