Android Handler消息派发机制源码分析
注:这里只是说一下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方法,执行我们设定的代码。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。