zoukankan      html  css  js  c++  java
  • Android之Handler基础篇

    一、Handler是什么?

      在Android开发中,使用消息队列(message)完成线程间通信。而使用消息队列的线程就是消息循环(message looper)。消息循环不断的检查消息队列,是否有新消息。消息循环是由一个线程和一个looper组成;looper对象管理着线程的消息队列。

      Android的主线程也是一个消息循环,也具有一个Looper,主线程所有的任务都是由looper完成。消息循环是由一个线程和一个looper组成,looper对象管理着线程的消息队列;因此,looper不断的从消息队列中抓取消息,然后完成消息指定的任务。

      PS: 线程默认情况下,是没有消息循环(Looper)的,在Android中,只有主线程默认就是Looper(消息循环)。在新创建的线程中,使用Looper,要先创建一个Looper才行。

      从下面图中了解一下Runnable、Message、MessageQueue、Looper、Handler含义:

                    (此图来自于其它书籍资料)

      将这此含义揉合在一起就是一个消息从发出到执行的整个过程:

                  (此图来自于其它书籍资料)

      从上面这两个图中,我们可以了解到:

      1. Runnable和Message压入到MessageQueue中,形成一个消息集合。

      2. Looper在不断的循环,不停的在做某一件事,比如:上图中Looper在不停的从MessageQueue中拿出Item,再传递给Handler执行。

      3. Handler在不断的去做某一具体的事情,比如:Handler收到一个消息,去解析一个后台返回的数据,再将其更新到UI上。

      从上面来看,Handler和Thread从表像上看确实没有直接的关系,但是因为:

      1.  每个Thread只能对应一个Looper;

      2. 每个Looper只能对应一个MessageQueue;

      3. 每个MessageQueue有N个Message;

      4. 每个Message最多指定一个Handler来处理;

      由此,可以推出Thread和Handler是一对多的关系。而Handler有两方面作用:

      1. 处理Message,作为Message处理者。

      2. 负责将Message压入MessageQueue中。 

    二、Message与Handler

      Message与Handler是成对出现的,Message是消息,而Handler是消息要完成任务的对象。

      消息是Message的一个实例,在实现一个消息时,要同时实现Message类的一些实例变量,

      • what: 用户定义的Int类型消息代码,用来描述消息。
      • obj: 随消息一起发送的用户指定的对象,即消息传递的数据。
      • target:完成消息指定任务的目标,即用来完成消息指定任务的对象。

      Handler是完成消息或消息指定任务的对象,Handler不仅是完成消息的目标或对象,也是创建和发布消息(Message)的接口。

                     (图来源于Android权威指南)

    • Looper拥有message的消息队列,所以,message必须在Looper上发布或读取。
    • 一个Handler仅一个Looper相关联,一个Message也仅与一个目标Handler(message目标)相关联。而Looper拥有消息的整个队列。

      在看看下面这个图,

     

     

                  (图来源于Android权威指南)

     

    从上面这个图中,可以看出,有多个Handler与一个Looper相关联,这说明一个Handler的message与另一个Handler的message放于同一个消息队列。

     三、Handler使用

      1. 使用Handler.obtainMessage(...)方法会从公共循环消息队列中,获取message。

      2. 使用Handler.sendToTarget()方法,会方法消息发送给与message相关联的Handler。而Handler会将message放于Looper的消息队列尾部。

      3. Looper在消息队列中,获取到特定的消息后,将其发送给消息目标(与之相关联的Handler)去处理。消息一般在Handler(消息目标)的handlerMessage(...)实现方法处理消息指定要完成的任务。一般,要继承Handler基类,覆盖handlerMessage()方法。

     四、传递Handler

      Handler类的一个实例,可以作为函数参数,传递给其它子线程。

      主线程拥有一个Handler和Looper消息循环,在线程中,主线程上创建一个Handler,会自动与主线程的Looper相关联。将主线程创建的Handler传递给另一个子线程,传递出去的Handler始终会与创建它的线程的Looper保持联系。因此,任何已传出的Handler负责处理的消息,都将在主线程的消息队列中处理。

      那么,就可以通过这种方式,在子线程中,去更新主线程的事件,数据,或者UI。

    五、在新线程中,创建Looper(消息循环)

      在主线程中不用创建Looper是因为App启动时,创建主线程中默认创建了Looper,并且一个线程中,只能有一个Looper。存在多个系统会报错。

      Looper为什么不会堵塞主线程,提示ANR(application not responding)?

      因为,主线程中的Activity和所有事件都是通过Looper执行的。Looper有一个消息队列,在不断的接收事件消息和执行事件。此中的堵塞是指Looper循环不被堵塞,而非Looper堵塞线程。

  • 相关阅读:
    [转]linux下的fms2流媒体服务器搭建六部曲之四格式转换篇
    Linux 信号signal处理函数
    FMS在linux下安装时的问题处理
    Linux 下让你的C程序在后台运行
    Linux 信号signal处理机制
    Flash Media Server 2 无限制许可文件
    JavaScript动态控制网页元素事件
    自定义MessageBox的窗口颜色,字体等属性
    [转]linux下的fms2流媒体服务器搭建六部曲之一ffmpeg安装篇
    [转]linux下的fms2流媒体服务器搭建六部曲之三FlashMediaServer安装篇
  • 原文地址:https://www.cnblogs.com/naray/p/8810594.html
Copyright © 2011-2022 走看看