【内核研究】处理者_Handler

虽然MessageQueue提供了直接读/写的函数接口。但对于程序猿来说,一般不直接读/写消息队列。之前了解到,在Looper.loop()函数中。当取出消息后,会回调msg.target对象的handleMessage()函数。而msg.target的类型正是Handler。

    /**
     *  Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    public static final void loop() {
        Looper me = myLooper();
        MessageQueue queue = me.mQueue;
        while (true) {
            Message msg = queue.next(); // might block
            //if (!me.mRun) {
            //    break;
            //}
            if (msg != null) {
                if (msg.target == null) {
                    // No target is a magic identifier for the quit message.
                    return;
                }
                if (me.mLogging!= null) me.mLogging.println(
                        ">>>>> Dispatching to " + msg.target + " "
                        + msg.callback + ": " + msg.what
                        );
                msg.target.dispatchMessage(msg);
                if (me.mLogging!= null) me.mLogging.println(
                        "<<<<< Finished to    " + msg.target + " "
                        + msg.callback);
                msg.recycle();
            }
        }
    }

一般使用Handler类向消息队列中发送消息,并重载Handler类的handleMessage()函数加入消息处理代码。

Handler对象仅仅能加入到有消息队列的线程中,否则会发生异常。以下代码是Handler类的构造函数:

    /**
     * Default constructor associates this handler with the queue for the
     * current thread.
     *
     * If there isn‘t one, this handler won‘t be able to receive messages.
     */
    public Handler() {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<?

extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        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 = null;
    }

注意这句代码:

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can‘t create handler inside thread that has not called Looper.prepare()");
        }

由以上代码能够得出结论,在构造Handler对象前。必须已经运行过Looper.prepare(),但prepare()不能被运行两次。

以下是Looper.prepare()的代码:

     /** Initialize the current thread as a looper.
      * This gives you a chance to create handlers that then reference
      * this looper, before actually starting the loop. Be sure to call
      * {@link #loop()} after calling this method, and end it by calling
      * {@link #quit()}.
      */
    public static final void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }

创建Handler对象能够在运行Looper.loop()函数之前。也能够在运行之后。

在以往的应用程序开发中,一般在Activity的初始化代码中加入Handler对象。其实,在Activity对象被构造前,Activity所在的线程已经运行了Looper.prepare()函数。详细可查看以下的链接。

http://blog.csdn.net/manoel/article/details/39499747

一个线程中能够包括多个Handler对象。在Looper.loop()函数中。不同的Message相应不同的Handler对象,从而回调不同的handleMessage()函数。

时间: 2024-08-04 03:47:12

【内核研究】处理者_Handler的相关文章

SQLite内核研究

先从全局的角度把握SQLite内核各个模块的设计和功能.SQLite采用了层次化.模块化的设计,而这些使得它的可扩展性和可移植性非常强.而且SQLite的架构与通用DBMS的结构差别不是很大,所以它对于理解通用DBMS具有重要意义.SQLite的内核总的来说分为三个部分,虚拟机(Virtual Machine).Back-end(后端)和compiler(编译器). 1.虚拟机(Virtual Machine)VDBE是SQLite的核心,它的上层模块和下层模块都是本质上都是为它服务的.它的实现

【Android 内核研究】理解Context

写在前面的话 非常感谢柯元旦所赠的<Android内核剖析>一书.通过对本书的学习,让我对Android内核有了更深一层次的理解.本文是<Android内核剖析>的学习笔记. Context是什么 一个Context意味着一个场景,一个场景就是用户和操作系统交互的一个过程.在广义上,这个所谓的过程应该包括前台界面和后台数据. 举个例子,比如当你打电话的时候,场景包括电话程序对应的界面以及隐藏在界面后的数据. 从程序的角度来看,一个Activity就是一个Context,一个Serv

【内核研究】消息队列_MessageQueue

消息队列采用排队方式对消息进行处理,即先到的消息会先得到处理,但如果消息本身指定了被处理的时刻,则必须等到该时刻才能处理该消息.消息在MessageQueue中使用Message类表示,队列中的消息以链表的结构进行保存,Message对象内部包含一个next变量,该变量指向下一个消息对象. MessageQueue中的两个主要函数是"取出消息"和"添加消息",分别是next()和enquenceMessage(). next()函数 final Message ne

Linux内核学习笔记

1.vanbreaker的专栏 2.LinuxKernel Exploration 3.DroidPhone的专栏 4.Linux内核研究以及学习文档和ARM学习以及研究的开放文档   [力荐] 5.Linux内核之旅 6.时钟管理系统和中断子系统 7. http://www.cnblogs.com/bastard/category/412387.html

linux内核数据结构学习总结(undone)

本文旨在整理内核和应用层分别涉及到的数据结构,从基础数据结构的角度来为内核研究作准备,会在今后的研究中不断补充 目录 1. 进程相关数据结构 1) struct task_struct 2. 内核中的队列/链表对象 3. 内核模块相关数据结构 2) struct module 1. 进程相关数据结构 0x1: task_struct 我们知道,在windows中使用PCB(进程控制块)来对进程的运行状态进行描述,对应的,在linux中使用task_struct结构体存储相关的进程信息,task_

Android内核剖析.pdf:

下载地址:网盘下载 由柯元旦编著的<Android内核剖析>详细分析了Android内核的内部机制,包括窗口管理系统.Activity管理系统.输入法框架.编译系统等,为Android内核定制及高级应用程序开发提供技术参考. <Android内核剖析>适合于所有Android相关的工程师及产品经理,还可作为相关培训机构的教材. 柯元旦,1981年生于陕西咸阳,2003年毕业于西安电子科技大学通信工程学院:2003-2006年,创立了一家设计公司,提供便携式媒体播放器解决方案,基于T

Android内核剖析pdf

下载地址:网盘下载 由柯元旦编著的<Android内核剖析>详细分析了Android内核的内部机制,包括窗口管理系统.Activity管理系统.输入法框架.编译系统等,为Android内核定制及高级应用程序开发提供技术参考. <Android内核剖析>适合于所有Android相关的工程师及产品经理,还可作为相关培训机构的教材. 柯元旦,1981年生于陕西咸阳,2003年毕业于西安电子科技大学通信工程学院:2003-2006年,创立了一家设计公司,提供便携式媒体播放器解决方案,基于T

信息安全系统设计基础第一周学习总结

第一节 Linux系统 1:Linux系统      登录Linux后,我们就可以在#或$符后面去输入命令,有的时候命令后面还会跟着选项(options)或参数(arguments).       即Linux中命令格式为:command[options][arguments].但有些命令也不需要跟着选项或参数.   选项是调整命令执行行为的开关,选项不同决定了命令的显示结果不同.   参数是指命令的作用对象.  2 :man命令       1是普通的Linux命令(用户命令帮助)      

Windows中断那些事儿

搞内核研究的经常对中断这个概念肯定不陌生,经常我们会接触很多与中断相关的术语,按照软件和硬件进行分类: 硬件CPU相关: IRQ.IDT.cli&sti 软件操作系统相关: APC.DPC.IRQL 一直以来对中断这一部分内容弄的一知半解,操作系统和CPU之间如何协同工作也是很模糊.最近花了点时间认真把这块知识进行了梳理,不当之处,还请高手指出,先行谢过了! 本文旨在解答下面这些问题: 1.IRQ和IRQL之间是什么关系? 2.Windows是如何在软件层面上虚拟出IRQL这套中断机制的 3.A