Android Handler消息处理机制

来源:互联网 发布:大屏幕切换软件 编辑:程序博客网 时间:2024/05/16 18:46

一、概述

Android进程间通信的方式有如下几类:

  • Intent
  • Broadcust
  • Handler
  • AIDL

Android作为一智能平台,消息是处理不同模块或进程间的一种常见方式,其中Handler的通信机制对Framework来说是最常见的一种。当某一应用创建一进程后,其主线程将用于处理一消息队列,该消息队列用于管理顶层(top-level)应用对象(activities, broadcast receivers, etc)和他们创建的窗口。如果创建了一些线程,可以通过Handler与应用的主线程(the main application thread)进行通信,具体方法就是通过Handler的post或sendMessage方法来实现的。

Handler包括MessageQueue、Looper及内部接口Callback三个元素,MessageQueue用来收集消息(Message);Looper通过与特定的线程关联,来处理Message;Callback接口避免使用Handler子类的方法而添加的一个功能。

Handler有两个主要功能:

  • 安排Messages和Runnables被执行的时机;
    • 由如下方法实现该功能:
        post, postAtTime(Runnable, long),  postDelayed,sendEmptyMessage,  sendMessage,sendMessageAtTime,  sendMessageDelayed
  • 将某个action加入队列中并在另外一线程中执行;
    • 由如下方法实现该功能:
         sendMessage, sendMessageDelayed, sendMessageAtTime


二、Handler的功能

Handler有如下三个功能:

  • (1)消息循环
  • (2)消息发送
  • (3)消息处理

下面结合代码做详细分析:

1.消息循环

在消息处理机制中,消息都是存放在一个消息队列中去,而应用程序的主线程就是围绕这个消息队列进入一个无限循环的,直到应用程序退出。如果队列中有消息,应用程序的主线程就会把它取出来,并分发给相应的Handler进行处理;如果队列中没有消息,应用程序的主线程就会进入空闲等待状态,等待下一个消息的到来。在Android应用程序中,这个消息循环过程是由Looper类来实现的。 Looper.java -- 用来在某一线程内处理消息循环,即消息是在线程中被执行的。Google的一个经典使用模板为:

(1) handler eg:

class LooperThread extends Thread {public Handler mHandler;public void run() {    Looper.prepare();//将当前的线程跟一Looper关联起来,而创建Looper的同时也创建了一MessageQueue;    mHandler = new Handler() {//(1)从Looper中获取当前线程的Looper;(2)从Looper中获取MessageQueue;(3)将mCallback置为null;        public void handleMessage(Message msg) {            // process incoming messages here        }    };    Looper.loop();//处理流程   }} 

(2)loop循环

public static void loop() {    Looper me = myLooper();//(1)从当前线程中取出Looper;    .......    MessageQueue queue = me.mQueue;//(2)从Looper中取出消息队列;    .......    while (true) {        Message msg = queue.next(); // might block (3)从消息队列中获取一条消息;        .......            msg.target.dispatchMessage(msg);//(4)调用Handler中的方法,处理消息        .......            msg.recycle();        }    }

这里就是进入到消息循环中去了,它不断地从消息队列mQueue中去获取下一个要处理的消息msg,如果消息的target成员变量为null,就表示要退出消息循环了,否则的话就要调用这个target对象的dispatchMessage成员函数来处理这个消息,这个target对象的类型为Handler.

(3)Looper构造函数

private Looper() {    mQueue = new MessageQueue();    mRun = true;    mThread = Thread.currentThread();}

---由此可以看出,一Looper对应一MessageQueue、对应一Thread;而mQueue就是用来存放、移除消息的消息队列。

2. 消息的发送

在Hanlder类的构造函数中,主要就是初始成员变量mLooper和mQueue,这里的mLooper是Looper类的静态成员函数,通过它来获得一个Looper对象.Handler允许发送和处理Message和Runnable objects,他们都通过MessageQueue与某个线程关联。每个Handler实例都关联一个线程和MessageQueue,而该MessageQueue是由该线程创建。即Handler传递消息和Runnable objects到MessageQueue,当执行时将它们移出MessageQueue。

  • 发送消息(sendMessage)时,有两种方式,其调用关系为:sendMessage --> sendMessageDelayed --> sendMessageAtTime
    • 默认情况下立即发送;
    • 可以指定发送的时间;
  • 在sendMessageAtTime函数,首先得到应用程序的消息队列mQueue,接着设置这个消息的目标对象target,即这个消息最终是由谁来处理的:
    • msg.target = this; 这里将它赋值为this,即表示这个消息最终由这个Handler对象来处理
    • sent = queue.enqueueMessage(msg, uptimeMillis); 将这个消息加入到应用程序的消息队列中去

3. 消息的处理

消息的处理是在Looper类的loop成员函数中进行处理的,它从消息队列中获得消息对象msg后,就会调用它的target成员变量的dispatchMessage函数来处理这个消息。这个消息对象msg的成员变量target是在发送消息的时候设置好的,一般就通过哪个Handler来发送消息,就通过哪个Handler来处理消息。