假设你对RxJava1.x还不是了解,能够參考以下文章。

1. RxJava使用介绍 【视频教程】

2. RxJava操作符

  • Creating Observables(Observable的创建操作符) 【视频教程】

  • Transforming Observables(Observable的转换操作符) 【视频教程】

  • Filtering Observables(Observable的过滤操作符) 【视频教程】

  • Combining Observables(Observable的组合操作符) 【视频教程】

  • Error Handling Operators(Observable的错误处理操作符) 【视频教程】

  • Observable Utility Operators(Observable的辅助性操作符) 【视频教程】

  • Conditional and Boolean Operators(Observable的条件和布尔操作符) 【视频教程】

  • Mathematical and Aggregate Operators(Observable数学运算及聚合操作符) 【视频教程】

  • 其它如observable.toList()、observable.connect()、observable.publish()等等。 【视频教程】

3. RxJava Observer与Subcriber的关系 【视频教程】

4. RxJava线程控制(Scheduler) 【视频教程】

5. RxJava 并发之数据流发射太快怎样办(背压(Backpressure)) 【视频教程】


前言

在有心课堂《RxJava之旅》中有学员留言:map和doOnSubscribe默认调度器是IO调度器,这里说错了吧?

以下我们分析下。

在前面讲 Subscriber 的时候,提到过 Subscriber 的 onStart() 能够用作流程開始前的初始化。然而 onStart() 由于在 subscribe() 发生时就被调用了,因此不能指定线程。而是仅仅能运行在 subscribe() 被调用时的线程。这就导致假设 onStart() 中含有对线程有要求的代码(比如在界面上显示一个 ProgressBar,这必须在主线程运行),将会有线程非法的风险,由于有时你无法预測 subscribe() 将会在什么线程运行。

而与 Subscriber.onStart() 相相应的。有一个方法 Observable.doOnSubscribe() 。

它和 Subscriber.onStart() 相同是在 subscribe() 调用后并且在事件发送前运行。但差别在于它能够指定线程。

默认情况下, doOnSubscribe() 运行在 subscribe() 发生的线程;而假设在 doOnSubscribe() 之后有 subscribeOn() 的话,它将运行在离它近期的 subscribeOn() 所指定的线程。

演示样例代码:

Observable.create(onSubscribe)
.subscribeOn(Schedulers.io())
.doOnSubscribe(new Action0() {
@Override
public void call() {
progressBar.setVisibility(View.VISIBLE); // 须要在主线程运行
}
})
.subscribeOn(AndroidSchedulers.mainThread()) // 指定主线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);

subscribeOn 作用于该操作符之前的 Observable 的创建操符作以及 doOnSubscribe 操作符 ,换句话说就是 doOnSubscribe 以及 Observable 的创建操作符总是被其之后近期的 subscribeOn 控制 。没看懂不要紧,看以下代码你就懂了。

Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
subscriber.onNext(1);
subscriber.onCompleted();
}
})
.doOnSubscribe(new Action0() { @Override
public void call() {
System.out.println("00doOnSubscribe在线程" + Thread.currentThread().getName() + "中");
}
})
.subscribeOn(Schedulers.newThread())
.map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
System.out.println("map1在线程" + Thread.currentThread().getName() + "中");
return integer + "";
}
})
.doOnSubscribe(new Action0() { @Override
public void call() {
System.out.println("11doOnSubscribe在线程" + Thread.currentThread().getName() + "中");
}
})
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.map(new Func1<String, String>() {
@Override
public String call(String s) {
System.out.println("map2在线程" + Thread.currentThread().getName() + "中"); return s + "1";
}
})
.doOnSubscribe(new Action0() { @Override
public void call() {
System.out.println("22doOnSubscribe在线程" + Thread.currentThread().getName() + "中");
}
})
.subscribeOn(Schedulers.newThread())
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() { } @Override
public void onError(Throwable e) { } @Override
public void onNext(String s) {
System.out.println("onNext在线程" + Thread.currentThread().getName() + "中");
}
});

运行结果例如以下:

22doOnSubscribe在线程RxNewThreadScheduler-1中
11doOnSubscribe在线程RxIoScheduler-3中
00doOnSubscribe在线程RxNewThreadScheduler-2中
map1在线程RxNewThreadScheduler-2中
map2在线程RxIoScheduler-2中
onNext在线程RxIoScheduler-2中

依据代码和运行结果我总结例如以下:

  1. doOnSubscribe()与onStart()相似,均在代码调用时就会回调。但doOnSubscribe()能够通过subscribeOn()操作符改变运行的线程且越在后面运行越早;
  2. doOnSubscribe()后面紧跟subscribeOn(),那么doOnSubscribe()将于subscribeOn()指定的线程保持一致。假设doOnSubscribe()在subscribeOn()之后,他的运行线程得再看情况分析;
  3. doOnSubscribe()假设在observeOn()后(注意:observeon()后没有紧接着再调用subcribeon()方法)。那么doOnSubscribe的运行线程就是main线程,与observeon()指定的线程没有关系。
  4. 假设在observeOn()之前没有调用过subcribeOn()方法,observeOn()之后subscribe面()方法之前调用subcribeOn()方法,那么他会改变整个代码流程中全部调用doOnSubscribe()方法所在的线程。同一时候也会改变observeOn()方法之前全部操作符所在的线程(有个重要前提:不满足第2点的条件,也就是doOnSubscribe()后面没有调用subscribeOn()方法)。
  5. 假设在observeOn()前后都没有调用过subcribeOn()方法,那么整个代码流程中的doOnSubscribe()运行在main线程,与observeOn()指定的线程无关。同一时候observeOn()之前的操作符也将运行在main线程,observeOn()之后的操作符与observeOn()指定的线程保持一致。

今天就分析到这里,假设有问题请大家反馈交流。

RxJava中的doOnSubscribe默认运行线程分析的更多相关文章

  1. 关于Ubuntu修改默认运行级别

    第一种方法:(内核级别的)   Sudo vi /etc/default/grub 修改GRUB_CMDLINE_LINUX_DEFAULT=”quiet splash” 为:GRUB_CMDLINE ...

  2. Java如何获得运行线程的优先级?

    在Java编程中,如何获得运行线程的优先级? 以下示例使用setPriority()方法打印正在运行的线程的优先级. package com.yiibai; public class GettingT ...

  3. java中如何使正在运行中的线程退出

    终止线程的三种方法      有三种方法可以使终止线程.      1.  使用退出标志,使线程正常退出,也就是当run方法完成后线程终止.      2.  使用stop方法强行终止线程(这个方法不 ...

  4. android 不能在子线程中更新ui的讨论和分析

    问题描写叙述 做过android开发基本都遇见过 ViewRootImpl$CalledFromWrongThreadException,上网一查,得到结果基本都是仅仅能在主线程中更改 ui.子线程要 ...

  5. .NET中 类型,对象,线程栈,托管堆在运行时的关系

    .NET中 类型,对象,线程栈,托管堆在运行时的关系 The Relationship at Run Time between Types,Objects,A Thread's Stack,and T ...

  6. [读书心得] .NET中 类型,对象,线程栈,托管堆在运行时的关系

    .NET中 类型,对象,线程栈,托管堆 在运行时的关系 The Relationship at Run Time between Types,Objects,A Thread's Stack,and ...

  7. JVM 内部运行线程介绍

    转(http://club.alibabatech.org/article_detail.htm?articleId=4) JVM 内部运行线程介绍 作者:蒋家佳/觉梦(支付宝开发工程师) 浏览量: ...

  8. 大约Android 3.0后AsyncTask默认的单线程分析

    在Android下了很大的后台操作在需要的情况下.通常用于AsyncTask这个类.比方说,网络负载形象.访问server接口.一般的情况是使用一个的一例AsyncTask对象mTask,复制Asyn ...

  9. 线程之 CPthon中的GIL与Lock的分析与解决办法

    Cpython 中的GIL锁介绍 1. 前戏 In CPython, the global interpreter lock, or GIL, is a mutex that prevents mul ...

随机推荐

  1. OpenSceneGraph-3.2.0 源代码的编辑步骤

    到osg官网去下载源代码 官网 再把资源包下载下来叫作3dpart资源包. 源代码下载下来之后依照这个步骤来. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQ ...

  2. 【jquery】jquery 自定义滚动条

    可以自由的给滚动条定义背景,上下按钮,当然不仅仅是颜色,连图片当背景也可以.支持鼠标滚轮,点击滚动条滚轴定位,上下按钮久按加速,兼容 ie,firefox,chrome. 调用方法: $(" ...

  3. Java图形界面设计——substance皮肤

    http://jianweili007-163-com.iteye.com/blog/1141358 ————————————————————————————————————————————————— ...

  4. 小米3移动版 分区 调整/合并教程(16GB/64GB)

    (必读)版权声明:米3移动版TWRP Recovery为XueferH适配,分区脚本以及双数据置换脚本的知识产权,智力成果权归XueferH所有. 注:此教程仅适用于Xiaomi MI 3-移动版(1 ...

  5. Ubuntu下允许Root用户的操作 (图形界面登录、su切换……)

    Ubuntu安装后,root用户默认是被锁定了的,不允许登录,也不允许“su”到 root.虽然这样的设置使安全性更高一些,但对于开发者来 说就显得很不方便了.如何让Ubuntu允许root用户直接登 ...

  6. 关于Unity中的光照(三)

    法线贴图 次时代游戏用的比较多 1:法线贴图是凹凸贴图技术上 的一种应用,有时也称为Dot3(仿立体)凹凸纹理贴图;2: 法线贴图是不增加多边形的情况下,增强模型的细节;3: 法线贴图是高精度模型导出 ...

  7. Ogre GpuProgram分析

    和前面讲解的Compositor一样,GpuProgram也对应一种资源文件,意思我们可以直接写一个文件来完成,不需要了解相关的类. 但是就和winform一样,直接拖控件能完成大部分工作,假如如果需 ...

  8. 【转】【Android】Android Studio打包全攻略

    项目写完了,现在需要把应用上传到市场,问题出现—怎么把代码变成.apk(Android的可安装文件).1. 创建签名文件2. 填写好签名参数3. 生成APK注意:签名的密码和密匙的密码注意保管,不要忘 ...

  9. Going deeper with convolutions 这篇论文

    致网友:如果你不小心检索到了这篇文章,请不要看,因为很烂.写下来用于作为我的笔记. 2014年,在LSVRC14(large-Scale Visual Recognition Challenge)中, ...

  10. 用OpenGL实现跳跃的立体小球

    一.目的 掌握OpenGL中显示列表对象的使用方法. 二.示例代码 Github地址 #include "stdafx.h" #include <GL/glut.h> ...