用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. 一.Memcached企业服务

    1.Memcached是什么,有什么作用?            Memcached是一个开源的.高性能的内存缓存软件,从名称上看Mem就是内存的意思,而Cache就是缓存的意思.          ...

  2. 阿里云 asp.net core nginx 单机部署

    1. dotnet core 安装 https://www.microsoft.com/net/download#core 安装之前要安装依赖:yum install libunwind libicu ...

  3. springMVC的注解@PathVariable是什么?详情及用法解析

    在路由中定义变量规则后,通常我们需要在处理方法(也就是@RequestMapping注解的方法)中获取这个URL变量的具体值,并根据这个值(例如用户名)做相应的操作,Spring MVC提供的@Pat ...

  4. Crowd Control

    我的图论还是只会套模板 嘤嘤嘤 题目描述 The BAPC draws a large number of visitors to Amsterdam. Many of these people ar ...

  5. 大道至简伪代码读后感java为代码形式

    //愚公移山 import.java.大道至简.*; import.java.愚公移山.*; public class yishan //定义一个名为yishan的类 {//类定义的开始 public ...

  6. CSS样式表------第一章:样式表的基本概念

    CSS(Cascading Style Sheets,层叠样式表),控制页面样式外观,作用是美化HTML网页. 一. 样式表的基本概念 1.样式表的分类 (1)内联样式表  -----放在元素的开始标 ...

  7. java 解析URL里的主域名及参数工具类

    java 解析URL里的协议及参数工具类,解析URL中的主域名,并统一把协议修改成http或去掉协议 public class UrlDomainUtils { private static fina ...

  8. Number of Digit One(Medium)

    1.算法说明: 如3141592,在m(digitDivide)=100时,即要求计算百位上"1"的个数 其中a为31415,b为92,31415中出现了3142次"1& ...

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

    #include<stdio.h> main() { int c; c=getchar(); while (c !=EOF) { if (c=='\t') { c='\\'; putcha ...

  10. supervisor安装与配置实践版

    应用场景 系统:centos7 需求:监控一个swooleWebSocket.php文件,程序使用的是8080端口,挂了自动被supervisor拉起来 一.首先要安装supervisor软件 yum ...