`
v5qqbrowser
  • 浏览: 356093 次
文章分类
社区版块
存档分类
最新评论

解析Android消息处理机制:Handler/Thread/Looper & MessageQueue

 
阅读更多


本文个人觉得写得很好,所以转来收藏。

原文地址:http://blog.csdn.net/thl789/article/details/6601558






解析Android消息处理机制

——Handler/Thread/Looper & MessageQueue

田海立@CSDN

2011/07/12

Keywords: Android Message HandlerThread Looper UML


本文解析Android如何利用Handler/Thread/Looper以及MessageQueue来实现消息机制的内部实现。知道了它的内部实现机理之后,以后再遇到使用它们时候的任何问题就驾轻就熟、迎刃而解了。

Android利用执行在HandlerThread线程中的Looper的相应消息分发/处理,与其他线程中的消息发送结合,实现完整的消息处理机制。本文首先介绍这些消息处理过程中的参与者之间的关系,然后结合WifiService消息处理的实际实例,讲解消息处理的全过程,最后还从线程视图的角度,重新审视一下线程同步模型。


一、HandlerThread/Looper/MessageQueue的前世今生

下图是从Froyo从抽取出的HandlerThread、Looper和MessageQueue的关系图。他们被定义在package android.os。

图一:HandlerThread/Looper/MessageQueue实例关系

HandlerThread是一个Thread,继承自Thread。它保留着对Looper实例的引用,不过这里还看不到HandlerThread、Looper和MessageQueue如何实例化,这要到二、HandlerThread/Looper/MessageQueue实例化之后才能看清如何实现的。

一看便知,Looper的构造函数是私有的,外界无法直接实例化之;要实例化,只有通过Looper::prepare()。这样HandlerThread就与Looper建立了对应关系。对如何建立的是不是已经迫不及待了,那就接着看下一小节。

二、HandlerThread/Looper/MessageQueue实例化

上一节只是看了HandlerThread、Looper和MessageQueue之间的静态视图关系,他们具体如何实例化的,还要看动态的实例初始化过程。

图二:HandlerThread/Looper实例化


  • HandlerThread是一个Thread,在它被实例化并执行start()[序列1&2]之后,它的run()方法会在它自己的线程空间执行[序列3]。
  • 上节已经提到了Looper的实例化是通过Looper::prepare实现的,图中可以看到Looper::prepare()正是在HandlerThread::run()中被调用而实例化[序列4&5]的。
  • MessageQueue是在Looper的私有构造函数Looper()中实例化的。

总结一下,HandlerThread是被显式地通过new创建的实例,而与它绑定在一起的Looper是在HandlerThread的执行过程中被实例化的,相应的MessageQueue也是在这个过程中实例化的。

三、Looper::loop分发处理消息

上节重点讲了HandlerThread/Looper的实例化过程,它发生在Thread::run()这也是线程运行的关键,从图二也看到了Looper::loop()这个消息处理的核心正是在这里执行的,下面就看看它到底做了什么。

图三:Looper::loop()处理


图中的所有序列是发生在一个无限循环体while (true) {}中的。

  • mQueue:MessageQueue是Looper保留的一份引用,通过它的next()[序列1]获取MessageQueue中的下一个要处理的消息,这个过程中如果没有相应的消息,执行它的线程会用this.wait()释放它所拥有的MessageQueue的对象锁而等待。
  • 一旦有消息到来[序列2],Looper会用获得的Message的Handler(msg.target)来分发处理消息[序列3&4]。消息处理完之后,还要回收[序列5]。

四、Handler实现具体消息处理

在Looper::loop()消息处理的顺序图里看到了Handler,这个消息分发处理的参与者。下面结合WifiHandler这个具体的Handler看它如何参与到消息的发送、分发和处理的。


4.1 Handler实例化

WifiService中定义了如下的WifiHandler。

图四、消息的发送、分发、处理者Handler


看Handler的构造函数是需要Looper的,从上面的分析知道,Looper是在HandlerThread执行中实例化的,Looper实例如何获得的呢?看图一&图二,知道HandlerThread保留着Looper的应用mLooper,并可通过getLooper()被外面获取。而Handler的mQueue: MessageQueue可以通过mLooper.mQueue获得。


所以,Wifi的HandlerThread,WifiHandler可以这样实例化:

  1. HandlerThreadwifiThread=newHandlerThread("WifiService");
  2. wifiThread.start();
  3. mWifiHandler=newWifiHandler(wifiThread.getLooper());

4.2 消息发送

图五、消息发送

通过Message::obtain()可以建立起Message和Target/Handler,what之间的关系,并得到一个Message msg[序列1&2];然后通过msg.sendToTarget()就可以用Handler来具体发送消息了[序列3&4];通过一系列的调用,最后会通过MessageQueue::enqueueMessage()把消息放到mMessages上[序列7],还会通过this.notify()通知正在等待新消息的线程,重新拥有MessageQueue的对象锁,而处理该消息。

图六、MessageQueue与Message的关系

至此,消息的发送,分发,处理基本上介绍完毕。


4.3 消息处理

而要具体处理消息,从图三的序列4就可知道,整个框架的最后消息的处理是通过Handler::handleMessager(msg: Message)来完成。所以如果有自己具体要处理的消息,只要override Handler的handleMessage(msg: Message)方法,并加入自己特定的对消息的处理即可。


要处理消息,就看看Message的属性里都有什么。

图七、Message属性


重点关注public属性what是区分具体什么消息;可以带参数arg1, arg2。

五、重新审视

5.1 应用指南

上面介绍了消息处理的全过程,这些对于只是用来发送和处理消息的应用者来说,可能有些繁杂,这里梳理一下从应用者角度看,怎么使用之。

其实四、Handler实现具体消息处理中的WifiService就是一个典型的应用场景。

实现一个Handler的子类,并Override handleMessage()方法,亦即,实现消息处理函数handleMessage()。然后分别创建HandlerThread和Hanlder继承类的实例。这样就可以如4.2里那样发消息了,而消息处理在handleMessage()中进行。

从应用者角度看,Looper和MessageQueue是消息处理的内部机制,可以不关注它的实现细节(唯一要知道的,Handler实例化的时候,需要通过HandlerThread获得Looper的实例,从而可以传递给Handler)。


5.2 线程角度

下面再从线程的角度看一下,消息处理过程中参与的线程,以及这些线程之间的同步。

显然的,这里有线程HandlerThread的参与,而且Looper::loop()就是执行在HandlerThread的run()方法里,也就是在HandlerThread里执行,这也就是说消息的分发处理和执行是在HandlerThread的线程上下文中。另外,还有至少一个线程存在,也就是创建了HandlerThread的线程B,以及执行消息发送的线程C,B和C有可能是同一线程。

消息的发送是在另外一个线程里,就是因为有了多个线程的存在,才有了线程的同步操作。可再次关注一下图三和图五中实现线程同步的Java原语wait()/notify()。

结束语

写本文的初衷并不是为了写它而写它,是在研究Android中的Wifi实现时,遇到了实现Wifi的各种具体操作都是通过消息来实现的,就想探讨一下ANDROID消息处理机制,这样就边看边用ROSE画了图,等到消息的发送/接收/处理的过程都看完了,再回头看一下整个UML图,这不就整个一完整的消息处理机制嘛!

工作这么多年过来了,回过头来看看,自己积累了什么呢,再看一下5、6年前鄙人的BLOG发现那时还是留下了些东西的,而且写本文时,重温Java的线程同步机制时,看到当时写的东西,发现如果是当时是自己理解的东西,并且用自己擅长的领域表达出来,自己回头再看时,一目了然,几个UML图就能解决问题了。

参考资料

Google Android source Froyo(2.2) git://android.git.kernel.org/platform/manifest.git

田海立 解析JVM线程同步机制http://blog.csdn.net/thl789/article/details/566494

修正记录

2011/07/18 修改标题、摘要及关键词

消息发送分发处理的主要参与者是Looper, Handler,还有Thread的执行。很多应用场景有他们参与就可完成,HandlerThread倒是WifiService处理时消息处理的一个特例,所以,在这些关键点上去掉HandlerThread。


(本文可自由转载,但请给出原文链接:http://blog.csdn.net/thl789/article/details/6601558)。

***************************** 全文结束 *******************************


分享到:
评论

相关推荐

    Thread,Looper,Handler,Message,MessageQueue,MessagePool之间的关系

    NULL 博文链接:https://null-point.iteye.com/blog/1356138

    活用Android的Message Queue

     你可以诞生Handler之对象来与Looper沟通,以便push新讯息到Message Queue里;或者接收Looper(从Message Queue取出)所送来的讯息。  线程A的Handler对象参考可以传递给别的线程,让别的线程B或C等能送讯息来给...

    android+多线程机制的讲解和例子

    1.Looper:一个线程可以产生一个Looper对象,由它来管理此线程里的Message ...每一个线程里可含有一个Looper对象以及一个MessageQueue数据结构。在你的应用程序里,可以定义Handler的子类别来接收Looper所送出的消息。

    了解Android核心:Looper,Handler和HandlerThread

    Looper 使线程保持活动状态,循环 MessageQueue 并向相应 Handler 的进程发送消息。 Thread 通过调用 Looper 的 quit() 方法终止。 Handler 及其组件 Handler:框架的重要对象,它具有双重责任。它绑定到给定线程...

    活用Android的Message_Queue(2)

     UI thread 通常就是main thread,而Android启动程序时(即诞生Process时)会替它建立一个Message Queue。  当然需要一个Looper之对象,来管理该Message Queue。  我们可以诞生Handler之对象来push新讯息到...

    Android中的消息处理实例之一

    本文介绍了Android中的消息处理机制,给出了Android消息处理中的几个重点类Handler、Message、MessageQueue、Looper、Runnable、Thread的详细介绍,提供了两个消息处理的实例代码,并深入Android源代码分析了使用...

    Thread、Handler和HandlerThread关系详解

    ,这个题目有点意思,对于很多人来说,可能对Thread和Handler很熟悉,主要涉及到Android的消息机制(Handler、Message、Looper、MessageQueue),详见《 从Handler.post(Runnable r)再一次梳理Android的消息机制(以及...

    Android中的消息处理实例之二

    本文介绍了Android中的消息处理机制,给出了Android消息处理中的几个重点类Handler、Message、MessageQueue、Looper、Runnable、Thread的详细介绍,提供了两个消息处理的实例代码,并深入Android源代码分析了使用...

    Android 面试宝典

    2)Handler:你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息. 3) Message Queue(消息队列):用来存放线程放入的消息. 4)线程:UI thread通常...

    Android编程之消息机制实例分析

    2.Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper(从Message Queue取出)所送来的消息。 3. Message Queue(消息队列):用来存放线程放入的消息。 4.线程:UI ...

    Android App在线程中创建handler的方法讲解

    5.Looper:消息循环,从MessageQueue中取出Message进行处理; 6.HandlerThread:继承Thread,实例化时自动创建Looper对象,实现一个消息循环线程. 在Android开发中经常会使用到线程,一想到线程,一般都会想到: new ...

    Mindroid.cpp:Mindroid.cpp是一个受Google Android操作系统启发的应用程序框架

    Mindroid.cpp C ++应用程序框架Mindroid是一个应用程序框架... 消息传递和并发框架主要基于Thread,Looper,Message,MessageQueue和Handler类。 为了方便起见,还有AsyncTask类,对于进程间通信,还有其他一些类,例

    全面总结Android中线程的异步处理方式

    一、概述 Handler 、 Looper 、Message 这三者都与...其实Looper负责的就是创建一个MessageQueue,然后进入一个无限循环体不断从该MessageQueue中读取消息,而消息的创建者就是一个或多个Handler 。 二、源码解析

    Android_Studio_Handler:Android Handler 执行绪教学

    Android Handler 执行绪...每一个执行绪都可以有一个讯息伫列(Message Queue)和一个循环器(Looper),在Android中建立的UI执行绪具有讯息伫列和一个循环器,其它worker执行绪预设并没有(可使用HandlerThread产生具有讯息

    深入Android HandlerThread 使用及其源码完全解析

    关联篇:深入Android的消息机制源码详解-Handler,MessageQueue与Looper关系 关联篇:Handler内存泄漏及其解决方案 本篇我们将来给大家介绍HandlerThread这个类,以前我们在使用线程执行一个耗时任务时总会new一个...

    Android 消息队列模型详解及实例

    Android系统的消息队列和消息循环都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列(Message Queue)和一个消息循环(Looper)。Android中除了UI线程(主线程),创建的工作线程默认是没有...

    代码分析Android消息机制

    Handler的运行主要由两个类来支撑:Looper与MessageQueue。熟悉开发的朋友都知道在子线程中默认是无法创建Handler的,这是因为子线程中不存在消息队列。当需要创建一个与子线程绑定的Handler时,标准代码如下: ...

    Android 消息机制问题总结

    Android的消息机制几乎是面试必问的话题,当然也并不是因为面试,而去学习,更重要的是它在Android的开发中是必不可少的,占着举足轻重的地位,所以弄懂它是很有必要的。下面就来说说最基本的东西。 Looper 作用: ...

    浅谈Android中线程池的管理

    说到线程就要说说线程机制 Handler,Looper,MessageQueue 可以说是三座大山了 Handler Handler 其实就是一个处理者,或者说一个发送者,它会把消息发送给消息队列,也就是Looper,然后在一个无限循环队列中进行取出...

    积分管理系统java源码-alibaba-Interview-preparation:阿里巴巴实习生面试个人准备

    积分管理系统java源码 ...Android线程 为什么要同步 Android中使用多线程的方法 裸new一个Thread(失控线程,不推荐) ...Android线程模型就是消息循环,Looper关联MessageQueue,不断尝试从MessageQueue取出Message来

Global site tag (gtag.js) - Google Analytics