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

Android Handler消息派发机制源码分析

程序员文章站 2024-03-05 16:27:31
注:这里只是说一下sendmessage的一个过程,post就类似的 如果我们需要发送消息,会调用sendmessage方法 public final b...

注:这里只是说一下sendmessage的一个过程,post就类似的
如果我们需要发送消息,会调用sendmessage方法

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

这个方法会调用如下的这个方法 

public final boolean sendmessagedelayed(message msg, long delaymillis)
{
 if (delaymillis < 0) {
  delaymillis = 0;
 }
 return sendmessageattime(msg, systemclock.uptimemillis() + delaymillis);
}

接下来设定延迟时间,然后继续调用sendmessageattime方法 

public boolean sendmessageattime(message msg, long uptimemillis) {
 messagequeue queue = mqueue;
 if (queue == null) {
  runtimeexception e = new runtimeexception(
    this + " sendmessageattime() called with no mqueue");
  log.w("looper", e.getmessage(), e);
  return false;
 }
 return enqueuemessage(queue, msg, uptimemillis);
}

这里获得了消息队列,检查队列是否存在,然后返回enquemessage的方法的执行结果,这个结果是说明消息能否进入队列的一个布尔值 

private boolean enqueuemessage(messagequeue queue, message msg, long uptimemillis) {
 msg.target = this;
 if (masynchronous) {
  msg.setasynchronous(true);
 }
 return queue.enqueuemessage(msg, uptimemillis);
}

这里是对消息进行入队处理,下面就是在messagequeue中对消息进行入队 

boolean enqueuemessage(message msg, long when) {
 if (msg.target == null) {
  throw new illegalargumentexception("message must have a target.");
 }
 if (msg.isinuse()) {
  throw new illegalstateexception(msg + " this message is already in use.");
 }

 synchronized (this) {
  if (mquitting) {
   illegalstateexception e = new illegalstateexception(
     msg.target + " sending message to a handler on a dead thread");
   log.w(tag, e.getmessage(), e);
   msg.recycle();
   return false;
  }

  msg.markinuse();
  msg.when = when;

  message p = mmessages;
  boolean needwake;
  if (p == null || when == 0 || when < p.when) {
   // new head, wake up the event queue if blocked.
   msg.next = p;
   mmessages = msg;
   needwake = mblocked;
  } else {
   // inserted within the middle of the queue. usually we don't have to wake
   // up the event queue unless there is a barrier at the head of the queue
   // and the message is the earliest asynchronous message in the queue.
   needwake = mblocked && p.target == null && msg.isasynchronous();
   message prev;
   for (;;) {
    prev = p;
    p = p.next;
    if (p == null || when < p.when) {
     break;
    }
    if (needwake && p.isasynchronous()) {
     needwake = false;
    }
   }
   msg.next = p; // invariant: p == prev.next
   prev.next = msg;
  }

  // we can assume mptr != 0 because mquitting is false.
  if (needwake) {
   nativewake(mptr);
  }
 }
 return true;
}

就是对传递过来的消息进行一些封装然后放到队列中,至此我们的sendmessage处理完毕,返回的结果是进队是否成功的布尔值,那么究竟消息之后是如何被处理的呢?
我们可以看到在handler构造的时候记录了一个looper对象,也记录了一个回掉函数 

public handler(callback callback, boolean async) {
 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 = callback;
 masynchronous = async;
}

这里的mylooper方法返回的是当前线程关联的一个looper对象

 public static @nullable looper mylooper() {
 return sthreadlocal.get();
} 

当looper实例化了以后会执行自己的prepare方法然后执行loop方法,loop方法就是不断的读取消息队列中的消息然后执行相应的操作的方法,因为是在其他线程中执行的循环所以不会影响其他线程 

public static void loop() {
 final looper me = mylooper();
 if (me == null) {
  throw new runtimeexception("no looper; looper.prepare() wasn't called on this thread.");
 }
 final messagequeue queue = me.mqueue;

 // make sure the identity of this thread is that of the local process,
 // and keep track of what that identity token actually is.
 binder.clearcallingidentity();
 final long ident = binder.clearcallingidentity();

 for (;;) {
  message msg = queue.next(); // might block
  if (msg == null) {
   // no message indicates that the message queue is quitting.
   return;
  }

  // this must be in a local variable, in case a ui event sets the logger
  printer logging = me.mlogging;
  if (logging != null) {
   logging.println(">>>>> dispatching to " + msg.target + " " +
     msg.callback + ": " + msg.what);
  }

  msg.target.dispatchmessage(msg);

  if (logging != null) {
   logging.println("<<<<< finished to " + msg.target + " " + msg.callback);
  }

  // make sure that during the course of dispatching the
  // identity of the thread wasn't corrupted.
  final long newident = binder.clearcallingidentity();
  if (ident != newident) {
   log.wtf(tag, "thread identity changed from 0x"
     + long.tohexstring(ident) + " to 0x"
     + long.tohexstring(newident) + " while dispatching to "
     + msg.target.getclass().getname() + " "
     + msg.callback + " what=" + msg.what);
  }

  msg.recycleunchecked();
 }
}

在循环中如果读取到了消息,就会执行dispatchmessage方法,然后分派完消息之后再执行一次recycleunchecked方法来重用这个message,我们看到dispatchmessage方法 

public void dispatchmessage(message msg) {
 if (msg.callback != null) {
  handlecallback(msg);
 } else {
  if (mcallback != null) {
   if (mcallback.handlemessage(msg)) {
    return;
   }
  }
  handlemessage(msg);
 }
}

这里看到直接执行了一个handlermessage方法,这个方法是一个回调方法,我们是必须实现的,否则handler什么都不会做,为什么呢?还记得刚刚说构造handler的时候我们记录了一个callback的回掉吗?handler中的这个handlermessage方法是一个空方法,如果我们重写了这个方法,在回调的时候就会执行我们先写下的代码,也就是接收到消息之后要做什么。 

public interface callback {
 public boolean handlemessage(message msg);
}

public void handlemessage(message msg) {
}

这里简单说下整个过程: 
当我们实例化一个handler的子类并重写handlemessage方法之后,这个时候系统已经帮我们做了几个事情 
1.实例化了一个消息队列messagequeue 
2.实例化了一个关联的looper对象,并让looper不断的读取消息队列
3.把我们重写的handlemessage方法记录为我们需要回调的方法 
当我们执行handler的sendmessage方法的时候,系统会把我们传过去的message对象添加到消息队列,这个时候如果looper读取到了消息,就会把消息派发出去,然后回调handlemessage方法,执行我们设定的代码。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。