RxJava2基础教程(二)线程控制和操作符

RxJava2的线程控制和操作符

Rx线程控制

Rx的链式调用:

这里利用String代替耗时的网络操作
Observable.just("我是网络请求操作")
         // 被观察者线程  即onNext操作线程
        .subscribeOn(Schedulers.io()) 
        // 观察者线程  
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer<String>() {
    @Override
    public void accept(String s) throws Exception {
        Logger.d(s);
        textview.setText(s);
    }
}, new Consumer<Throwable>() {
    @Override
    public void accept(Throwable throwable) throws Exception {
        Logger.d(throwable);
    }
});

subscribeOn(Schedulers) 和 observeOn(Schedulers) 来指定被观察者和观察者操作线程 Schedulers 有如下几种

Schedulers介绍线程池大小
Schedulers.io()通常用于网络,读写文件等io密集型的操作无上限线程池
Schedulers.computation()CPU计算密集型的操作(计算操作)CPU 核心数
Schedulers.newThread()常规创建新线程
AndroidSchedulers.mainThread()Android主线程(RxAndroid 提供的)

Rx 常用操作符

Rx的操作符非常多 要看文档来慢慢学习积累 先介绍几种常用的
创建操作符
create defer from just Timer 等等这些就是创建操作符
变换操作符 用于数据转换操作
buffer flatMap map scan groupBy window

map
实现字符串转换数字

            String num = "123";
            String str = "我不是数字";

            Observable.just(num).map(new Function<String, Integer>() {
                @Override
                public Integer apply(String s) throws Exception {
                    //使用str转换会出异常 则在 onError中收到异常
                    return Integer.parseInt(s);
                }
            }).subscribe(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) throws Exception {
                    mMsg.setText(integer + "");
                }
            }, new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    Logger.d(throwable);
                }
            });
日志:
D/PRETTYLOGGER: ║ Thread: main
D/PRETTYLOGGER: ║ 123

flatMap 应用
需求有2个网络操作相互依赖 比如 登录操作A 可以拿到用户头像 请求头像操作B 来显示缓存头像

    Observable.just("用户名和密码")
    .flatMap(new Function<String, ObservableSource<String>>() {
        @Override
        public ObservableSource<String> apply(String s) throws Exception {
            //A 网络操作 获取UserInfo
            User user = ...                                
            return Observable.just(user.getAvatar());
        }
    })
    .flatMap(new Function<String, ObservableSource<Bitmap>>() {
        @Override
        public ObservableSource<Bitmap> apply(String url) throws Exception {
            //B 通过url获取Bitmap
            Bitmap avatar = ImageLoad.with(url);
            return Observable.just(avatar);
        }
    })
    //指定转换过程的线程
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<Bitmap>() {
        @Override
        public void onSubscribe(Disposable d) {
        }
        @Override
        public void onNext(Bitmap bm) {
            imageView.setImageBitmap(bm);          
        }
        @Override
        public void onError(Throwable e) {
            Logger.d(e);
        }
        @Override
        public void onComplete() {
            Logger.d("onComplete");
        }
    });
    丫! 代码怎么这么长 还不如原始的操作方式 A 的回调中再使用 B 。 其实不然,这只是在学习理解操作符的过程,后期这些学习会为我们带来更加简洁的使用方式

过滤操作符
filter

    Observable.just("123456我")
            .filter(new Predicate<String>() {
                @Override
                public boolean test(String s) throws Exception {
                    //类似校验操作  不满足条件不会继续传输
                    return s.contains("我");
                }
            })
            .subscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<String>() {
                @Override
                public void accept(String s) throws Exception {
                    Logger.d(s);
                }
            });   
    日志: 123456我 ,onComplete
    如果发送123456 则 最终直接 onComplete 

Debounce 操作符会过滤掉发射速率过快的数据项(官方文档)。

解决频繁请求数据的需求
    Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(ObservableEmitter<String> emitter) throws Exception {
            for (int i = 1; i < 5; i++) {
                emitter.onNext(i + "");
                //  模拟产生过快发送
                Thread.sleep(i * 100);
            }
            emitter.onComplete();
        }
    })      //定义 速度过滤 超过此时长的可以发送出去
            .debounce(300, TimeUnit.MILLISECONDS)
            //数据校验器
            .filter(new Predicate<String>() {
                @Override
                public boolean test(String s) throws Exception {
                    return !TextUtils.isEmpty(s);
                }
            })
            //数据转换器具
            .flatMap(new Function<String, ObservableSource<List<String>>>() {
                @Override
                public ObservableSource<List<String>> apply(String s) throws Exception {

                    List<String> list = new ArrayList<>();
                    list.add(s);
                    list.add("服务器列表数据1");
                    list.add("服务器列表数据2");
                    list.add("服务器列表数据3");

                    return Observable.just(list);
                }
            })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<List<String>>() {
                @Override
                public void onSubscribe(Disposable d) {
                    Logger.d("onSubscribe");
                }

                @Override
                public void onNext(List<String> value) {
                    Logger.d("onNext:" + value);
                }

                @Override
                public void onError(Throwable e) {
                    Logger.d("onError:" + e);
                }

                @Override
                public void onComplete() {
                   Logger.d("onComplete");
                }
            });

switchMap 和 flatMap

官方文档说明是:
RxJava还实现了 switchMap 操作符。它和 flatMap 很像,除了一点:当原始Observable发射 一个新的数据(Observable)时,它将取消订阅并停止监视产生执之前那个数据的 Observable,只监视当前这一个。

这样去理解 发送A请求又发送了B请求,我们期望得到B的结果,然而由于A在服务器阻塞了,B先返回,紧接着A也返回了,这时候展示了A的结果。(常见的search接口) 这时候需要用到 switchMap

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值