文档章节

Handler详解

libvirus
 libvirus
发布于 2016/05/22 18:40
字数 1043
阅读 14
收藏 0

Handler详解

##一,概述 因为Android里的控件都是线程不安全的,更新UI的代码必须在主线程所有Google给我们提供了一个线程通信的类。 而且Android的各种事件,Activity,Service组件的方法回调,也是基于Hander的。 这就是Handler。其实他们主要是由三个主要的类构成 Looper , Handler , MessageQueue。

##二,Looper 我相信写过从主线程发送消息通知子线程的人都应该刻这一段代码

        Looper.prepare();
        Handler handler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
            }
        };
        Looper.loop();

为什么在主线程写Handler不用Looper.prepare(); Looper.loop();呢,那是因为主线程已经为我们做了这些工作。 我们可以看看这两行代码做了什么事。如下,Looper.prepare()主要是初始化工作,创建一个Looper对象放入ThreadLocal当中。然后新建一个MessageQueue对象。 我们通过Handler 发送的消息就放在这个队列当中。

public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

在看看Looper.loop()又做了点什么事情

    /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    //代码有删改,完整的代码请看源码
    public static void loop() {
        final Looper me = myLooper();
        final MessageQueue queue = me.mQueue;

        for (;;) {
            Message msg = queue.next(); // might block
            msg.target.dispatchMessage(msg);
            msg.recycleUnchecked();
        }
    }

这个方法很简单只是把死循环队列当中的消息,有消息就msg.target.dispatchMessage去执行,dispatchMessage这个方法是不是很熟悉呢,其它msg.target 对象就是Handler对象,至于怎么放到Message当中去的,后边在讲。有细心的同学可能注意到这是一个死循环,而且队列有可能会阻塞,前面有讲到主线和里替我们 初始化了Looper。那么主线程为又是怎么执行代码的呢。当然原因很简单方法回调和事件都是通过主线程里的Handler发送到队列里,然后执行的。比如你手机卡的 时候你点返回,没有反应,你连点几次的话,又退出程序了,因为事件都在队列里,执行完一个在执行别一个。 ##三,Handler 上面说到Looper.loop()从队列里取出来的Message给了msg.target,我说他是一个Handler对象,我们看看他是怎么放入消息中的。

    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

所有发送消息的方法最后都是调用的这个方法。我们看到msg.target=this所有消息在放入消息队列之前都会持有发送消息的Handler对象。这就是哪个Handler发送的消息, 哪个Handler负责处理。 那么,Handler是怎么和Looper关联起来呢,Handler怎么知道消息要放入哪个队列的呢。原来在

   public Handler(Callback callback, boolean async) {
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

我们看到从这个Looper.myLooper()方法里得到的Looper对象。

    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }

现在知道Looper对象是怎么来的了吧。如果在非主线程里new Handler那就必须要在这个线程里初始化一个Looper对象,用ThreadLocal保存起来。new Handler的时候 要查检在本线程里有没有这个对象,如果没有会报错。

##三,总结 对于Rxjava,RxAndroid 这类不用写Handler的类库,内部应该也是需要通过Handler post代码的。所以这种线程间通信的方法一定要明白。 当然这还些知道还很浅显。最核心的是消息队列的实现,消息队列是由Linux里的管道实现的。希望以后搞明白了那一块的代码,在来更新。

© 著作权归作者所有

共有 人打赏支持
libvirus
粉丝 0
博文 2
码字总数 1315
作品 0
朝阳
程序员
Handler和Looper详解

关于这个话题,其实很早之前就想撰写相关来的稳当来加加深映像,或者当做技术笔记,但是一直都不知道从哪里开始比较合适.先看看网上给出的相关的定. Hanlder作用: 1)执行计划任务,你可以再预定...

z.net
2013/06/19
0
0
Android HandlerThread详解

转载请注明出处:http://blog.csdn.net/vnanyesheshou/article/details/75073307 对于Handler不太懂的可以参考我的这两篇文章: Android Handler的基本使用 深入理解Handler、Looper、Messa...

VNanyesheshou
2017/07/14
0
0
JFinal路由规则原理详解

《JFinal路由规则原理详解》 JFinal的路由规则比较灵活,提供了多种规则方式匹配,可以满足大多数应用场景。如果不满足您的需求,也可以轻松使用handler去扩展自己的路由规则。 访问localho...

山东小木
2016/02/15
827
0
详解Android中Handler的使用方法

在Android开发中,我们经常会遇到这样一种情况:在UI界面上进行某项操作后要执行一段很耗时的代码,比如我们在界面上点击了一个”下载“按钮,那么我们需要执行网络请求,这是一个耗时操作,...

我叫leo-
2016/04/27
88
0
springmvc处理流程详解

一、首先了解springMVC的组件定义及用途 1.DisPatcherServlet:前端控制器(不需要程序员开发) 用户请求到达前端控制器,它相当于MVC模式中的C(Controller),DispatcherServlet是整个流程...

J星星点灯
2017/09/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

OSChina 周三乱弹 —— 我居然在 osc 里追剧

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @舆情风控小组 :分享王菲的单曲《笑忘书》 《笑忘书》- 王菲 手机党少年们想听歌,请使劲儿戳(这里) @艾尔库鲁斯:如果给大家一个选择的机...

小小编辑
45分钟前
70
6
rabbitMq的客户端使用笔记

1、channel声明队列的queueDeclare方法的参数解析 durable: 是否持久化, 队列的声明默认是存放到内存中的,如果rabbitmq重启会丢失,如果想重启之后还存在就要使队列持久化,保存到Erlang自...

DemonsI
53分钟前
0
0
“全新” 编程语言 Julia开箱体验

本文共 851字,阅读大约需要 3分钟 ! 概 述 Julia 是一个 “全新”的高性能动态编程语言,前两天迎来了其 1.0 正式版的重大更新。Julia集 Python、C、R、Ruby 之所长,感觉就像一种脚本语言...

CodeSheep
今天
12
0
软件自动化测试初学者忠告

题外话 测试入门 很多受过高等教育的大学生经常问要不要去报测试培训班来入门测试。 答案是否。 高等教育的合格毕业生要具备自学能力,如果你不具备自学能力,要好好地反省一下,为什么自己受...

python测试开发人工智能安全
今天
5
0
java并发备忘

不安全的“先检查后执行”,代码形式如下: if(条件满足){ //这里容易出现线程安全问题//doSomething}else{//doOther} 读取-修改-写入 原子操作:使用CAS技术,即首先从V中读取...

Funcy1122
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部