RX系列五 | Schedulers线程控制

RX系列五 | Schedulers线程控制



在我们上一篇文章中的,我们的小例子里有这么一段代码

//网络访问
.observeOn(Schedulers.io())

事实上,我们在使用网络操作的时候,便可以控制其运行在哪个线程中,而Schedulers类,有四个方法,分别是

  • Schedulers.immediate();
  • Schedulers.newthread();
  • Schedulers.io();
  • Schedulers.computation();

以及RxAndroid中的AndroidSchedulers有一个

  • AndroidSchedulers.mainThread();

这些都是操作线程的方法,我们都知道RxJava在异步方面很优秀,那我们应该怎么去体现他尼,先来看下这几个函数的具体含义吧

Schedulers.immediate()

作用于当前线程运行,相当于你在哪个线程执行代码就在哪个线程运行

Schedulers.newthread();

运行在新线程中,相当于new Thread(),每次执行都会在新线程中

Schedulers.io();

一看便知,I/O操作,比如文件操作,网络操作等,他和newThread有点类似,不过I/O里面有一个死循环的线程池来达到最大限度的处理逻辑,虽然效率高,但是如果只是一般的计算操作,不建议放在这里,避免重复创建无用线程

Schedulers.computation()

一些需要CPU计算的操作,比如图形,视频等

AndroidSchedulers.mainThread();

指定运行在Android主线程中

我们现在就来模拟这个操作,比如我们去加载一张图片,那么我们使用okhttp的话,代码应该怎么写

  @Override
    public void onClick(final View v) {
        switch (v.getId()) {
            case R.id.load_img:
                Observable.create(new ObservableOnSubscribe<Bitmap>() {
                    //主线程执行
                    @Override
                    public void subscribe(final ObservableEmitter<Bitmap> e1) throws Exception {
                        //进行网络操作 解析图片
                        OkHttpClient client = new OkHttpClient();
                        Request request = new Request.Builder().url(IMG_URL).build();
                        //异步方法
                        client.newCall(request).enqueue(new Callback() {
                            @Override
                            public void onFailure(Call call, IOException e) {
                                e1.onError(e);
                            }

                            @Override
                            public void onResponse(Call call, Response response) throws IOException {
                                if (response.isSuccessful()) {
                                    byte[] bytes = response.body().bytes();
                                    Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                                    e1.onNext(bitmap);
                                    e1.onComplete();
                                }
                            }
                        });
                    }
                }).subscribe(new Observer<Bitmap>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.e("MainActivity", "onSubscribe");
                    }

                    @Override
                    public void onNext(Bitmap bitmap) {
                        Log.e("MainActivity", "onNext");

                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.e("MainActivity", "onError" + e.toString());
                    }

                    @Override
                    public void onComplete() {
                        Log.e("MainActivity", "onComplete");
                    }
                });
                break;
        }
    }

嗯,可以的,然后我们运行,会出现什么日志尼

com.liuguilin.schedulerssample E/MainActivity: onSubscribe
com.liuguilin.schedulerssample E/MainActivity: android.os.NetworkOnMainThreadException

他提示我们不能在主线程进行网络操作,那好,可以下的结论是subscribe在主线程,那现在我们的Schedulers就派上用场了,我们只需要

.subscribeOn(Schedulers.io())

让其在I/O操作即可,而这些含义,上面也都有提及,那我们现在运行,可以看到如下的打印

com.liuguilin.schedulerssample E/MainActivity: onSubscribe
com.liuguilin.schedulerssample E/MainActivity: onNext
com.liuguilin.schedulerssample E/MainActivity: onComplete

好的,走了onnext说明我们加载是成功的,因为我是加载图片,所有我现在来加载这张图片,这个很简单,我们只需要设置就好了

@Override
public void onNext(Bitmap bitmap) {
    Log.e("MainActivity", "onNext");
    iv_img.setImageBitmap(bitmap);

}

但是当你运行 你就会发现,又出现错误了

CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

这个错误你一定不陌生,这就是在子线程更新UI的错误,其实这里也很好理解,就是我们在网络操作的时候是在子线程中,是吧,所有我们设置图片才会有这样的错误,其实解决的办法,就是将我们的消费者切换成我们的主UI线程就好了,添加一行

.observeOn(AndroidSchedulers.mainThread())

好的,现在我们运行一下看下效果

OK,全部的代码就这么点,就一个小知识点,但是一定要清楚他的工作流程

    @Override
    public void onClick(final View v) {
        switch (v.getId()) {
            case R.id.load_img:
                Observable.create(new ObservableOnSubscribe<Bitmap>() {
                    //主线程执行
                    @Override
                    public void subscribe(final ObservableEmitter<Bitmap> e1) throws Exception {
                        //进行网络操作 解析图片
                        OkHttpClient client = new OkHttpClient();
                        Request request = new Request.Builder().url(IMG_URL).build();
                        //异步方法
                        client.newCall(request).enqueue(new Callback() {
                            @Override
                            public void onFailure(Call call, IOException e) {
                                e1.onError(e);
                            }

                            @Override
                            public void onResponse(Call call, Response response) throws IOException {
                                if (response.isSuccessful()) {
                                    byte[] bytes = response.body().bytes();
                                    Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                                    e1.onNext(bitmap);
                                    e1.onComplete();
                                }
                            }
                        });
                    }
                }).subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Observer<Bitmap>() {
                            @Override
                            public void onSubscribe(Disposable d) {
                                Log.e("MainActivity", "onSubscribe");
                            }

                            @Override
                            public void onNext(Bitmap bitmap) {
                                Log.e("MainActivity", "onNext");
                                iv_img.setImageBitmap(bitmap);

                            }

                            @Override
                            public void onError(Throwable e) {
                                Log.e("MainActivity", "onError" + e.toString());
                            }

                            @Override
                            public void onComplete() {
                                Log.e("MainActivity", "onComplete");
                            }
                        });
                break;
        }
    }

在线程操作的时候,自己只要清楚使用哪一个Schedulers就好了,这个例子比较简单,但是如果你的逻辑很复杂的话,而且需要来回的线程切换的时候,这个rxjava的优势就出来了,我们以后慢慢的深入吧!

Sample下载:http://download.csdn.net/detail/qq_26787115/9792294

时间: 2024-10-26 09:16:57

RX系列五 | Schedulers线程控制的相关文章

RX系列四 | RxAndroid | 加载图片 | 提交表单

RX系列四 | RxAndroid | 加载图片 | 提交表单 说实话,学RxJava就是为了我们在Android中运用的更加顺手一点,也就是RxAndroid,我们还是先一步步来,学会怎么去用的比较好,之前的三篇算是铺垫,让你有一点认识,那Rx在Android中有什么好处呢?我们先模拟一些原始功能和他对比下 一.加载图片 很多人说Rx出来之后,是编程思想的一种进阶,实际上我学习了这种思想之后,确实是觉得有了很大的改变,不过,需要一点学习成本再加上,需要对原先的思想有些改观,使得我依旧有点不适应

iOS流布局UICollectionView系列五——圆环布局的实现

iOS流布局UICollectionView系列五--圆环布局的实现 一.引言         前边的几篇博客,我们了解了UICollectionView的基本用法以及一些扩展,在不定高的瀑布流布局中,我们发现,可以通过设置具体的布局属性类UICollectionViewLayoutAttributes来设置设置每个item的具体位置,我们可以再扩展一下,如果位置我们可以自由控制,那个布局我们也可以更加灵活,就比如创建一个如下的circleLayout: 这种布局方式在apple的官方文档中也有

ASP.NET MVC+EF框架+EasyUI实现权限管理系列(8)-DbSession线程内唯一

原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(8)-DbSession线程内唯一 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2):数据库访问层的设计Demo    (3):面向接口编程   (4 ):业务逻辑层的封装  (5):前台Jquery easyUI实现   (6):EF上下文实例管理   (7):DBSession的封装 前言:通过上篇博客我们完成了对DbSession的代码编写,DbSession就相

C语言线程控制的程序设计

问题描述 C语言线程控制的程序设计 编写一个程开启3个线程,的ID分别为A.B.C每个线程将自己的ID在线程上打印出来10遍,要求输出结果按照ABC的顺序显示: 如:ABCABC....依次递推 解决方案 用一个互斥锁加三条件变量就好了啊,首先初始化时设置A条件,A执行打印后设置B条件,B执行打印后设置C条件,C执行打印后设置A条件这样循环......... 解决方案二: 这个题目的考察点是如何保护共用数据吧,给数据加好锁就OK了 解决方案三: 用3个互斥,在线程里等待条件成立,然后执行动作 解

RX系列一 | ReactiveX根源 | 观察者模式分析

RX系列一 | ReactiveX根源 | 观察者模式分析 Rx的响应式编程算是很火了,对吧,但是我的工作基本上就不会接触,所以学习的比较晚,到现在才分享给大家,我们一点点的去学,当你看完这整个系列的博客的时候,我相信你最起码也是能把Rx的操作放入你的项目中,既然如此,那我们就开始吧! 一.资料 现在的资料都烂大街了,我也是看这些资料学的,先分享出来 ReactiveX GitHub RxAndroid GitHub RxJava GitHub Android开发技术周报特刊之RxJava&Rx

走近Flex组件系列(五):数据组件(Dataehoose,DateFiled)与文本组件

走近Flex组件系列(五):数据组件(Dataehoose,DateFiled)与文本组件(Label,Text) Flex中的日期组件Dataehoose很简单,其功能就是提供一个直观的日期选择界面,比较常用且需要记住的就是他的change事件. 1 <mx:DateChooser x="263" y="19" showToday="true" 2 change="displayDate(DateChooser(event.ta

Bing Maps进阶系列五:通过DeepEarth的MiniMap控件为Bing Maps扩展迷你小地图

Bing Maps进阶系列五:通过DeepEarth的MiniMap控件为Bing Maps扩展迷你小地图 Bing Maps Silverlight Control虽然为我们提供了简洁.方便的开发模型,但也有许多不足之处,比如我们想实现一个迷你小地图功能,对于Bing Map Silverlight Control就没有这样的内置控件.但不必费心费神的自己去开发一个这样的控件来实现这个功能,因为在DeepEarth中已经为我们提供了这样一个控件,首先看看在Bing Maps(http://cn

浅谈.NET下的多线程和并行计算(五)线程池基础 上

池(Pool)是一个很常见的提高性能的方式.比如线程池连接池等,之所以有这些池是因为线程和数 据库连接的创建和关闭是一种比较昂贵的行为.对于这种昂贵的资源我们往往会考虑在一个池容器中放置 一些资源,在用的时候去拿,在不够的时候添点,在用完就归还,这样就可以避免不断的创建资源和销毁 资源. 如果您做过相关实验的话可能会觉得不以为然,似乎开1000个线程也用不了几百毫秒.我们要这么想 ,对于一个高并发的环境来说,每一秒假设有100个请求,每个请求需要使用(开和关)10个线程,也就 是一秒需要处理10

[JAVA100例]066、线程控制

/** * <p>Title: 线程控制</p> * <p>Description: 实现对线程的控制,中断.挂起.恢复.停止</p> * <p>Copyright: Copyright (c) 2003</p> * <p>Filename: threadCtrl.java</p> * @version 1.0 */ public class threadCtrl{ public static void mai