用Schedulers(调度器)实现多任务(并发,Concurrency)的例子

废话不多说我们看一下有关于RxJava的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private Subscription _subscription;
@OnClick(R.id.btn_start_operation) //
public void startLongOperation() {
_progress.setVisibility(View.VISIBLE);
_log("Button Clicked");
_subscription = _getObservable()//
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(_getObserver()); // Observer
}
private Observable<Boolean> _getObservable() {
return Observable.just(true).map(new Func1<Boolean, Boolean>() {
@Override
public Boolean call(Boolean aBoolean) {
_log("Within Observable");
_doSomeLongOperation_thatBlocksCurrentThread();//长时间的操作,阻塞线程
return aBoolean;
}
});
}
private Observer<Boolean> _getObserver() {
return new Observer<Boolean>() {
//....一些操作
};
}

这段代码比较简单,只涉及了一个知识点Schedulers调度器

Schedulers

概括:线程调度器,用来达到切换线程的效果。

在Android开发中,由于UI线程是不能够被阻塞的,不然就会产生ANR导致程序崩溃。所以我们经常的处理是,两种方法:

1.新开线程(或者线程池中)处理阻塞的操作:

1
2
3
4
5
6
7
8
9
10
11
new Thread(new Runnable() {
@Override
public void run() {
try{
mEntity = getEntity();
mHandler.obtainMessage(1,mEntity).sendToTarget();
}catch (Exception e){
mHandler.sendEmptyMessage(0);
}
}
}).start();

大家可以看到,我们这里只是进行了一个简单的IO操作,就陷入了这么谜一般的缩进。要是设计更加复杂的呢?

而且我们还要用Handler处理消息,造成了编码的撕裂感! 虽然我个人对Handler并不反感,但在编码的时候,它的存在的确让我感到有点惆怅~~

2.回调处理

1
2
3
4
5
6
7
8
9
HttpClient.getInstance().get("http://www.qq.com",new HttpCallback(){
public void onSuccess(String result){
//...成功操作
}
public void onError(Exception e){
//...失败操作
}
});

这里我们随便写了一个获取QQ主页的首页数据的操作。 虽然现在看起来还是蛮简单的。 只有一层回调,但是要是我们要针对QQ返回的结果,再进行一次热门词汇的搜索文章,搜索出来的文章我还要获取第五篇文章,然后我再获取第五篇文章的评论呢?

这里就会陷入Callback Hell (回调地狱)! 维护起来真的是太恶心了!

3.小结一下Schedulers

Schedulers调度器的出现,保持了我们使用RxJava的链式调用,不会出现撕裂感,因为它可以帮我们游刃有余的进行线程切换,而不需要进行Hanlder或者回调!

也正是Schedulers的出现才让我下定决心学习RxJava的初衷! 这实在的太棒了(当然还有无穷无尽的操作符~~)

结束

1.关于Schedulers的原理

因为能力还没有到这里层度,毕竟RxJava和一般的库不一样,它里面涉及了很多“高端知识”而我也不敢乱说出来误导。 所以呢~这里附上前辈的分析吧(反正我看的是有点一头雾水):给 Android 开发者的 RxJava 详解 里面有一部分是涉及Schedulers分析的。

我觉得要是看不懂也没关系,随着我们使用的越来越多,没准在哪一天心血来潮想看看源码的时候突然就明白了呢~

在未来的学习,要是我突然明白了,我会尽快写一篇文章和大家讨论的~

2.附录:完整源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
public class ConcurrencyWithSchedulersDemoFragment
extends BaseFragment {
@Bind(R.id.progress_operation_running)
ProgressBar _progress;
@Bind(R.id.list_threading_log)
ListView _logsList;
private LogAdapter _adapter;
private List<String> _logs;
private Subscription _subscription;
@Override
public void onDestroy() {
super.onDestroy();
RxUtils.unsubscribeIfNotNull(_subscription);
ButterKnife.unbind(this);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
_setupLogger();
}
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_concurrency_schedulers, container, false);
ButterKnife.bind(this, layout);
return layout;
}
@OnClick(R.id.btn_start_operation)
public void startLongOperation() {
_progress.setVisibility(View.VISIBLE);
_log("Button Clicked");
_subscription = _getObservable()//
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(_getObserver()); // Observer
}
private Observable<Boolean> _getObservable() {
return Observable.just(true).map(new Func1<Boolean, Boolean>() {
@Override
public Boolean call(Boolean aBoolean) {
_log("Within Observable");
_doSomeLongOperation_thatBlocksCurrentThread();
return aBoolean;
}
});
}
/**
* Observer that handles the result through the 3 important actions:
* <p/>
* 1. onCompleted
* 2. onError
* 3. onNext
*/
private Observer<Boolean> _getObserver() {
return new Observer<Boolean>() {
@Override
public void onCompleted() {
_log("On complete");
_progress.setVisibility(View.INVISIBLE);
}
@Override
public void onError(Throwable e) {
Timber.e(e, "Error in RxJava Demo concurrency");
_log(String.format("Boo! Error %s", e.getMessage()));
_progress.setVisibility(View.INVISIBLE);
}
@Override
public void onNext(Boolean bool) {
_log(String.format("onNext with return value "%b"", bool));
}
};
}
// -----------------------------------------------------------------------------------
// Method that help wiring up the example (irrelevant to RxJava)
private void _doSomeLongOperation_thatBlocksCurrentThread() {
_log("performing long operation");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Timber.d("Operation was interrupted");
}
}
private void _log(String logMsg) {
if (_isCurrentlyOnMainThread()) {
_logs.add(0, logMsg + " (main thread) ");
_adapter.clear();
_adapter.addAll(_logs);
} else {
_logs.add(0, logMsg + " (NOT main thread) ");
// You can only do below stuff on main thread.
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
_adapter.clear();
_adapter.addAll(_logs);
}
});
}
}
private void _setupLogger() {
_logs = new ArrayList<String>();
_adapter = new LogAdapter(getActivity(), new ArrayList<String>());
_logsList.setAdapter(_adapter);
}
private boolean _isCurrentlyOnMainThread() {
return Looper.myLooper() == Looper.getMainLooper();
}
private class LogAdapter
extends ArrayAdapter<String> {
public LogAdapter(Context context, List<String> logs) {
super(context, R.layout.item_log, R.id.item_log, logs);
}
}
}

-Hans 2016.3.5 13:36

【RxJava Demo分析】(二)Schedulers线程调度器 · Hans Zone的更多相关文章

  1. 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

  2. RxJava 和 RxAndroid 五(线程调度)

    对rxJava不了解的同学可以先看 RxJava 和 RxAndroid 一 (基础)RxJava 和 RxAndroid 二(操作符的使用)RxJava 和 RxAndroid 三(生命周期控制和内 ...

  3. Fresco 源码分析(二) Fresco客户端与服务端交互(1) 解决遗留的Q1问题

    4.2 Fresco客户端与服务端的交互(一) 解决Q1问题 从这篇博客开始,我们开始讨论客户端与服务端是如何交互的,这个交互的入口,我们从Q1问题入手(博客按照这样的问题入手,是因为当时我也是从这里 ...

  4. ucore操作系统学习(六) ucore lab6线程调度器

    1. ucore lab6介绍 ucore在lab5中实现了较为完整的进程/线程机制,能够创建和管理位于内核态或用户态的多个线程,让不同的线程通过上下文切换并发的执行,最大化利用CPU硬件资源.uco ...

  5. Duilib源码分析(三)XML解析器—CMarkup

    上一节介绍了控件构造器CDialogBuilder,接下来将分析其XML解析器CMarkup: CMarkup:xml解析器,目前内置支持三种编码格式:UTF8.UNICODE.ASNI,默认为UTF ...

  6. springMVC源码分析--RequestParamMethodArgumentResolver参数解析器(三)

    之前两篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)和springMVC源码解析--HandlerMethodArgumentResol ...

  7. SDL2源代码分析3:渲染器(SDL_Renderer)

    ===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...

  8. qml demo分析(threadedanimation-线程动画)

    一.效果预览 使用过qml的同学都知道,使用qml做动画效果是非常简单的,再也不需要像QWidget那样,自己模拟一个动画,费时又费力,往往还达不到效果.今天我们就来分析下qml的两种动画实现方式,如 ...

  9. qml demo分析(maskedmousearea-异形窗口)

    一.效果展示 如本文的标题所示,这篇文章分析的demo是一个异形窗口,主要展示鼠标在和异形区域交互的使用,效果如图1所示,当鼠标移动到白云或者月亮上时,相应的物体会高亮,当鼠标按下时,物体会有一个放大 ...

随机推荐

  1. 迅为iTOP-开发板-驱动-can和rfid配置

    在迅为开发板中,在 4412,4418 以及 6818 中,有的开发板默认配置 RFID,有的默认配 置 CAN 驱动(IMX6 默认都配置). 本文档介绍如何配置 CAN 和 RFID 的驱动. 截 ...

  2. 画张自己能理解的dotnet core 微服务图

  3. android studio 3.2 bundle.gradle 与2.2区别

    参考:https://blog.csdn.net/MakerCloud/article/details/82898305

  4. ubuntu19.10——snap错误has install-snap change in progress

    使用软件商店安装时遇到问题 snap has install-snap change in progress 原因是之前的安装错误终止,使得现在的安装无法进行,解决方案: 终端输入: snap cha ...

  5. windows 安装MySQL服务 zip解压程序

    1:配置 my.ini 文件 如下: [mysql] default-character-set=utf8[mysqld] port=3306basedir=D:\\Program Files\\da ...

  6. [JSOI2019]节日庆典(Z-algorithm)

    要想让一个位置作为最小循环,其必须是最小后缀,然后一个字符串的最小后缀不超过O(logn)个,于是维护备选集合即可. 然而要在O(n)复杂度求解,需要求出原串后缀与原串的LCP长度,需要用Z-algo ...

  7. window下mysql安装步骤

    1. 官网下载mysql zip包 2. 解压后再D:\database\mysql\mysql-5.7.26-winx64下添加my.ini文件,文件内容如下: [mysql]# 设置mysql客户 ...

  8. 基于css完成网页的国际化

    css完成国际化 前提 在日常处理国际化的时候,通常是将key通过类似intl.xx(key)转换为对应环境的文案,可是如果需要在css中加入对应逻辑应该怎么做呢(比如在after的伪元素中显示不同的 ...

  9. 《C 程序设计语言》练习1-3

    #include<stdio.h> /*当fahr=0,20,...,300时,打印华氏温度与摄氏温度对照表; 浮点数版本*/ main () { float fahr,celsius; ...

  10. <c:if >标签的坑!!

    <c:if test="${trans.Transition}"> <input id="${trans.nextnode}" type=&q ...