06.RxJava初探

基本使用

在build.gradle中加入配置,注意,rxJava和rxAndroid版本一定要相互兼容,不然可能会报错More than one file was found with OS independent path 'META-INF/rxjava.properties'

    compile 'io.reactivex.rxjava2:rxjava:2.0.2'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.2'

被观察者订阅观察者,当被观察者状态改变,可以通知观察者进行操作

第一种写法:
Observable observable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> observableEmitter) throws Exception {
                 try {
                    //这三个方法分别对应着observer中的三个方
                    //法,调用哪个就执行observer中相应的方法
                    observableEmitter.onNext("星期一");
                    observableEmitter.onComplete();
                } catch (Exception e) {
                    e.printStackTrace();
                    observableEmitter.onError(new NullPointerException("发生异常"));
                }
            }
        });

        Observer<String> observer = new Observer<String>() {
            @Override
            public void onSubscribe(Disposable disposable) {
                LogUtils.i(TAG, "onSubscribe");
            }

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

            @Override
            public void onError(Throwable throwable) {
                LogUtils.i(TAG, "onError");
            }

            @Override
            public void onComplete() {
                LogUtils.i(TAG, "onComplete");
            }
        };
        observable.subscribe(observer);
第二种写法
Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<String> observableEmitter) throws Exception {
                LogUtils.i(TAG, "subscribe");
                //这三个方法同样和下边三个是对应的
                observableEmitter.onNext("onNext");
                observableEmitter.onComplete();
                observableEmitter.onError(new IllegalAccessException("发送错误"));
            }
        }).subscribe(new Consumer() {
            @Override
            public void accept(Object o) throws Exception {
                LogUtils.i(TAG, "subscribe(new Consumer() " + o.toString());
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                LogUtils.i(TAG, "new Consumer<Throwable>");
            }
        }, new Action() {
            @Override
            public void run() throws Exception {
                LogUtils.i(TAG, "new Action()");
            }
        });

线程控制

RxJava如何切换线程?

Schedulers.immerdiate():

直接在当前线程运行,相当于不指定线程,这是默认的Scheduler

Schedulers.newThread():

总是启用新线程,并在新线程执行操作

Schedulers.io():

I/O操作(读写文件,读写数据库,网络信息交互)所使用的Scheduler,行为模式和newThread()差不多,区别在于io的内部实现使用一个无数量上线的线程池,可以重用空闲线程,因此多数情况下io()比newThread更有效率,不要把计算工作放在io()中,可以避免创建不必要的线程

Schedulers.computation():

计算所使用的Scheduler,这个计算指的是CPU密集型计算,即不会被I/O等操作限制性能的操作,例如图形计算,这个Scheduler使用的固定的线程池,大小为CPU核数,不要把IO操作放在这里,否则等待时间会浪费cpu

AndroidSchedulers.mainThread():(rxAndroid中的类)

它指定的操作将在Android主线程运行

Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(@NonNull final ObservableEmitter<String> observableEmitter) throws Exception {
                String url1 = "http://is.snssdk.com/2/essay/discovery/v3/?iid=6152551759&aid=7";
                URL url = new URL(url1);
                //得到connection对象。
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                //设置请求方式
                connection.setRequestMethod("GET");
                //连接
                connection.connect();
                //得到响应码
                int responseCode = connection.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    //得到响应流
                    InputStream inputStream = connection.getInputStream();
                    //将响应流转换成字符串
                    String result = stream2String(inputStream);//将流转换为字符串。
                    LogUtils.i(TAG, "onSuccess");
                    observableEmitter.onNext(result);
                } else {
                    observableEmitter.onError(new Exception("失败"));
                }
            }
        })
           //指定网络请求在io线程,界面更新在主线程
           .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(@NonNull Disposable disposable) {
                LogUtils.i(TAG, "onSubscribe");
            }

            @Override
            public void onNext(@NonNull String s) {
                LogUtils.i(TAG, "onNext");
                mTextView.setText(s);

            }

            @Override
            public void onError(@NonNull Throwable throwable) {
                LogUtils.i(TAG, "onError");
                throwable.printStackTrace();
            }

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

常用操作符

map

map的作用简单来说就是我输入一个数据类型的对象,转换得到另一个我想要的数据类型的对象,例如下边,传入integer,得到String。

map操作符对原始的Observable发送的每一项数据应用一个你选择的函数,然后返回一个发射这些结果的Observable

Observable.just(1).map(new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Exception {
                return 1 + "哈哈,下雨了";
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                LogUtils.i(TAG, s);
            }
        });
flatMap

flatMap操作符使用一个指定的函数对原始Observable发射的每一项数据执行变换操作,这个函数返回一个本身也发射数据的Observable,然后flatMap合并这些Observables发射的数据,最后将合并后的结果当作它自己的数据序列发射

Observable.just(getUserParams()).flatMap(new Function<UserParams, ObservableSource<LoginResult>>() {
            @Override
            public ObservableSource<LoginResult> apply(UserParams userParams) throws Exception {
                //do something 模拟登录传入登录参数后获取到服务器返回值
                LoginResult result = new LoginResult(userParams);
                return Observable.just(result);
            }
        }).flatMap(new Function<LoginResult, ObservableSource<User>>() {
            @Override
            public ObservableSource<User> apply(LoginResult loginResult) throws Exception {
                //do something 模拟从登录返回值中根据userid获取到用户信息,返回User对象
                return Observable.just(new User());
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<User>() {
            @Override
            public void accept(User user) throws Exception {
                //显示用户姓名
                LogUtils.i(TAG, user.toString());
            }
        });
switchMap

将Observable发射的数据集合变换为Observables集合,然后只发射这些Observables最近发射的数据

Observable.just(s).filter(new Predicate<String>() {
            @Override
            public boolean test(String s) throws Exception {
                if (!TextUtils.isEmpty(s) && s.contains("a")) {
                    return true;
                }
                return false;
            }
        })//switchMap和flatMap只有一点区别,在这个场景下,由于每次输入的文字变化都会进行搜索,而且搜索
                //结果不一定是先请求的先返回,有可能是本来我要搜索abc,当我输入ab的时候进行了一次搜索,然后输入
                //完abc又请求了一次,但是由于各种原因,第一次请求的结果返回晚于第二次,那么第一次搜索的不是我想要
                //的结果,但是由于它返回的晚,反而把理想的搜索结果覆盖了,用switchMap可以解决这个问题,它会
                //返回最近一次请求的结果,即便是由于上边的原因导致的问题
        .switchMap(new Function<String, ObservableSource<List<String>>>() {
            @Override
            public ObservableSource<List<String>> apply(String s) throws Exception {
                List<String> list = new ArrayList<String>();
                list.add("搜索结果a");
                list.add("搜索结果B");
                return Observable.just(list);
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<List<String>>() {
                    @Override
                    public void accept(List<String> strings) throws Exception {
                        //将搜索结果展示在列表中
                        for (String string : strings) {
                            LogUtils.i(TAG, string);
                        }
                    }
                });

今天忙了很久,也只是在使用上了解了一些rxJava的东西,下一次会从源码层面分析

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容