欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

「Android」消息驱动Looper和Handler类分析

程序员文章站 2022-07-03 18:43:04
Android系统中的消息驱动工作原理: 1、有一个消息队列,可以往这个消息队列中投递消息; 2、有一个消息循环,不断的从消息队列中取得消息,然后处理。 工作流程: 1、事件源将待处理的消息加入到消息队列中,一般是加至队列尾部(优先级高的消息可以加至队列头),事件源提交的消息可以是按键、触摸等物理事 ......

android系统中的消息驱动工作原理:

1、有一个消息队列,可以往这个消息队列中投递消息;

2、有一个消息循环,不断的从消息队列中取得消息,然后处理。

 

工作流程:

1、事件源将待处理的消息加入到消息队列中,一般是加至队列尾部(优先级高的消息可以加至队列头),事件源提交的消息可以是按键、触摸等物理事件产生的消息,也可以是系统或应用程序发出的消息;

2、处理线程不断的从消息队列头中取出消息并处理。

 

在android系统中,这些工作主要由looperhandler实现:

looper类,用于封装消息循环,并且有一个消息队列;

handler类,封装消息投递、消息处理等接口。

 

一、looper类分析

looper用于封装了android线程中的消息循环,默认情况下一个线程是不存在消息循环(message loop)的,需要调用looper.prepare()来给线程创建一个消息循环,调用looper.loop()来使消息循环起作用,使用looper.prepare()和looper.loop()创建了消息队列就可以让消息处理在该线程中完成。

class looperthread extends thread
{
     public void run() 
   {
      looper.prepare();
       //代码1....       
      looper.loop();
        //代码2....
    }    
}         

(1)在 looper.prepare()中,定义一个threadlocal对象st,并构造一个looper对象设置到调用线程的局部变量st中。

    threadlocal是java中的线程局部变量类(thread local variable),该类有两个关键函数:

  • set:设置调用线程的局部变量
  • get:获取调用线程的局部变量

  因此,prepareh函数会在调用线程的局部变量中设置一个looper对象。这个调用线程就是looperthread的run线程。

private    looper(){
 //构造一个消息队列
 mqueue = new messagequeue();
 //得到当前线程的thread对象
 mthread  = thread.currentthread();        
}

  prepare函数中设置了一个looper对象,对象保存在这个调用线程的局部变量中。而looper 对象内部封装了一个消息队列。

 

(2)looper循环

  > 在loop()方法中,首先通过threadlocal的get方法获取创建的looper对象;

  > 之后取出这个looper的消息队列  messagequeue   queue = looper.mqueue; 

  > while循环中,处理消息:

while(true){
    message msg = queue.next();
    // 处理i消息,message对象中有一个target(handler类型)
    // 如果target为空,则退出消息循环   
    if (msg != null ) {
        if (msg.target == null) { return;  }

        // 调用该消息的handler,交给他的dispatchmessage函数处理。
        msg.target.dispatchmessage(msg);
        msg.recyle();
}
}

 

     因此,分析prepare和loop函数后,looper的作用有:

  1、封装了一个消息队列;  

  2、prepare函数把这个looper和调用prepare的线程(最终的处理线程)关联在i一起;

  3、处理线程调用loop函数,处理来自消息队列的消息   

    当事件源向looper发送消息时,消息加到looper的消息队列。该消息将由和looper绑定的处理线程来处理

  

 注:looper、message、handler的关系:

  1、looper中有一个message队列,存储的时一个个待处理的message;

  2、message中有一个handler,用来处理message。 

 

二、handler类分析

  handler中包括的成员:

    hadler.java:      

final messagequeue mqueue;       //handler中也有一个消息队列
final looper mlooper;                    
final  callback mcallback;              //i回调用的类

  在handler的构造函数中,handler中的消息队列最终会指向looper的消息队列。

(1)插入消息到looper消息队列 

  handler提供了一系列帮助完成创建消息和插入消息队列的函数。

  例如handler.java中sendmessage发送一个消息,将消息添加到消息队列末尾

public  final  boolean  sendmessage(message msg) {    
     return sendmessagedelayed(msg,  0);  
}

public final boolean senmessagedelayed(message msg, long delaymilis){
    ......
    return senmessage(msg, systemclock.uptimemillis() + delaymillis);   // 当前时间
}

public boolean sendmessagetime(message msg, long uptimemillis) {
   boolean sent = false;
   messagequeue queue = mqueue;

   if (queue != null) {
      msg.target = this; // 将targt设置为自己,然后加入到消息队列
      sent = queue.enqueuemessage(msg, uptimemillis);   
}
  return sentl
}

   (2)handler的消息处理

   在loop方法中,如果获得消息后会调用target的dispatchmessage函数,然后将这个消息派发给handler处理。

   dispatchmessage定义了一套消息处理的优先级机制:

    > messagu如果自带callback处理,则交给callback处理;

    > handler如果设置了全局的mcallback,则交给mcallback处理;

    > 如果上述都没有,消息则会被交给handler子类实现的handlemessage 来处理。(这需要从handler派生并重载handlemessage函数)