文档章节

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乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子:5.33起,其声呜呜然,如怨如慕,如泣如诉。余音袅袅,不绝如缕。分享Arch Enemy的单曲《Bridge Of Destiny (2009)》 《Bridge Of...

小小编辑
今天
250
4
what f,,

anlve
今天
9
0
初级开发-编程题

` public static void main(String[] args) { System.out.println(changeStrToUpperCase("user_name_abc")); System.out.println(changeStrToLowerCase(changeStrToUpperCase("user_name_abc......

小池仔
今天
15
0
现场看路演了!

HiBlock
昨天
23
0
Rabbit MQ基本概念介绍

RabbitMQ介绍 • RabbitMQ是一个消息中间件,是一个很好用的消息队列框架。 • ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的s...

寰宇01
昨天
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部