美文网首页安卓程序员RxJava + RetrofitAndroid 入门进阶
【Android】RxJava的使用(四)线程控制 —— Sch

【Android】RxJava的使用(四)线程控制 —— Sch

作者: 带心情去旅行 | 来源:发表于2016-05-22 00:21 被阅读10173次
    并没有关系的图

    前言

    经过前几篇的介绍,对RxJava对模式有了一定的理解:由Observable发起事件,经过中间的处理后由Observer消费。(对RxJava还不了解的可以出门左拐)
    之前的代码中,事件的发起和消费都是在同一个线程中执行,也就是说之前我们使用的RxJava是同步的~~~
    观察者模式本身的目的不就是后台处理,将处理结果回调给前台?这同步的是要哪样?所以,这篇为大家介绍RxJava的重要的概念——Scheduler

    参考:给 Android 开发者的 RxJava 详解
    (本文部分内容引用自该博客)

    介绍

    RxJava在不指定线程的情况下,发起时间和消费时间默认使用当前线程。所以之前的做法

            Observable.just(student1, student2, student2)
                    //使用map进行转换,参数1:转换前的类型,参数2:转换后的类型
                    .map(new Func1<Student, String>() {
                        @Override
                        public String call(Student i) {
                            String name = i.getName();//获取Student对象中的name
                            return name;//返回name
                        }
                    })
                    .subscribe(new Action1<String>() {
                        @Override
                        public void call(String s) {
                            nameList.add(s);
                        }
                    });
    

    因为是在主线程中发起的,所以不管中间map的处理还是Action1的执行都是在主线程中进行的。若是map中有耗时的操作,这样会导致主线程拥塞,这并不是我们想看到的。

    Scheduler

    Scheduler:线程控制器,可以指定每一段代码在什么样的线程中执行。
    模拟一个需求:新的线程发起事件,在主线程中消费

        private void rxJavaTest3() {
            Observable.just("Hello", "Word")
                    .subscribeOn(Schedulers.newThread())//指定 subscribe() 发生在新的线程
                    .observeOn(AndroidSchedulers.mainThread())// 指定 Subscriber 的回调发生在主线程
                    .subscribe(new Action1<String>() {
                        @Override
                        public void call(String s) {
                            Log.i(TAG, s);
                        }
                    });
    

    上面用到了subscribeOn(),和observeOn()方法来指定发生的线程和消费的线程。

    • subscribeOn():指定subscribe() 所发生的线程,即 Observable.OnSubscribe 被激活时所处的线程。或者叫做事件产生的线程。
    • observeOn():指定Subscriber 所运行在的线程。或者叫做事件消费的线程。

    以及参数Scheduler,RxJava已经为我们提供了一下几个Scheduler

    • Schedulers.immediate():直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler。
    • Schedulers.newThread():总是启用新线程,并在新线程执行操作。
    • Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。
    • Schedulers.computation():计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。
    • AndroidSchedulers.mainThread():它指定的操作将在 Android 主线程运行。

    多次切换线程

    看完上面的介绍想必对RxJava线程的切换有了一些理解,上面只是对事件的发起和消费制定了线程。如果中间有map之类的操作呢?是否可以实现发起的线程在新线程中,map的处理在IO线程,最后的消费在主线程中。

            Observable.just("Hello", "Wrold")
                    .subscribeOn(Schedulers.newThread())//指定:在新的线程中发起
                    .observeOn(Schedulers.io())         //指定:在io线程中处理
                    .map(new Func1<String, String>() {
                        @Override
                        public String call(String s) {
                            return handleString(s);       //处理数据
                        }
                    })
                    .observeOn(AndroidSchedulers.mainThread())//指定:在主线程中处理
                    .subscribe(new Action1<String>() {
                        @Override
                        public void call(String s) {
                            show(s);                       //消费事件
                        }
                    });
    

    可以看到observeOn()被调用了两次,分别指定了map的处理的现场和消费事件show(s)的线程。

    若将observeOn(AndroidSchedulers.mainThread())去掉会怎么样?不为消费事件show(s)指定线程后,show(s)会在那里执行?
    其实,observeOn() 指定的是它之后的操作所在的线程。也就是说,map的处理和最后的消费事件show(s)都会在io线程中执行。
    observeOn()可以多次使用,可以随意变换线程

    小结

    学会线程控制后才算是真正学会了使用RxJava。RxJava的使用十分灵活,想要对其熟悉使用只有一个办法,那就是多用啦,熟能生巧。

    以上有错误之处感谢指出

    参考:给 Android 开发者的 RxJava 详解
    (本文部分内容引用自该博客)

    相关文章

      网友评论

      • 8ad1764e191a:特地注册了个账号来评论。写得条例清晰,通俗易懂,感谢作者
        带心情去旅行:@FinleyLC 谢谢,相互学习
      • 0920ea02e3a0:佩服,佩服。我再梳理梳理你的这四篇攻略才算是入门了!
      • xingchueng:写的挺好的!
      • 154db6c439ab:写得很好,没有第五篇了吗?
      • Android猿来如此:言简意赅 谢谢楼主
      • 浅安流年:非常感谢。连读了你的四篇文章,对RxJava的用法有所了解了。
      • EnzoRay:看了好多篇,博主这篇确实简洁,看完可以基本使用,楼主后面还可以继续加深:blush: 。有些博主一开始就把FlatMap摆出来,看得人一脸懵逼。
        带心情去旅行:@DOAING 应该叫重新发射
        DOAING:我的理解就是 flatmap 就是二次拆分集合啊~~~~~
        HarryChen:同感 一来就flatmap的真的是要入门到放弃
      • 我累个擦:我一定要登录账号说一句,简洁明了,言简意赅!
      • 963274b5be88:我靠,这是我看的不下10片同样的Rxjava中讲的最详细最通俗易懂的一篇,把你的这个看完,真的浑身通透,看别人的看得我都是模模糊糊,都不知道讲的什么玩意。博主这篇文章也是用心写了,毕竟对于基础比较差的人来说,看懂才是最好的,灰常感谢
      • 恒等式古怪:看完了 谢谢大神
      • 有钱有所有:看来很多篇RxJava相关文章 ,都很难学会;本篇文章言简意赅,适合学习。最需要的就是这种简单易懂的好文章
      • 8b112aea8a4b:66666666666666666
      • d4d27c43a6d7:之前看完别人的博客还是模糊,答主的文章一边就明白了 灰常感谢~~~
        带心情去旅行:@菠菜_093d 不客气哈
      • 9a40856775b9:看了这个系列感觉非常舒服,谢谢
        带心情去旅行:@爱刘宇 不客气,希望能帮到像我一样的新手们
      • 斌哥老弟:言简意赅...但是subscribeOn()没怎么介绍
      • 落魄的安卓开发:灰常感谢。几篇看下来,可以基本使用。
      • 8b5e7c159a14:学习到这的时候发现AndroidSchedulers这个类没有,进而马上去下了jar包,添加后,gradle总是报错,心想会不会这个类有冲突,新建工程把RXandroid单独引入发现好了 :smile:
        作者,两个同时使用正常吗?
        带心情去旅行:@卤煮火烧大碗加肠我能吃仨 加入依赖后就可以用啦,没出现过你说的找不到类的问题
      • 帅气的猪猪:谢谢,写的非常易懂。最近才接触RxJava的使用,最需要的就是这种简单易懂的好文章 :smile:
        带心情去旅行:@帅气的猪猪 谢谢
      • 好男儿jt:可以得,言简意赅。实际引用的栗子比教少

      本文标题:【Android】RxJava的使用(四)线程控制 —— Sch

      本文链接:https://www.haomeiwen.com/subject/ypjorttx.html