Android消息机制Handler深入理解
概述
handler是android消息机制的上层接口。通过它可以轻松地将一个任务切换到handler所在的线程中去执行。通常情况下,handler的使用场景就是更新ui。
handler的使用
在子线程中,进行耗时操作,执行完操作后,发送消息,通知主线程更新ui。
public class activity extends android.app.activity { private handler mhandler = new handler(){ @override public void handlemessage(message msg) { super.handlemessage(msg); // 更新ui } } ; @override public void oncreate(bundle savedinstancestate, persistablebundle persistentstate) { super.oncreate(savedinstancestate, persistentstate); setcontentview(r.layout.activity_main); new thread(new runnable() { @override public void run() { // 执行耗时任务 ... // 任务执行完后,通知handler更新ui message message = message.obtain(); message.what = 1; mhandler.sendmessage(message); } } ).start(); } }
handler架构
handler消息机制主要包括:messagequeue、handler、looper这三大部分,以及message。
- message:需要传递的消息,可以传递数据;
- messagequeue:消息队列,但是它的内部实现并不是用的队列,而是通过单链表的数据结构来维护消息列表,因为单链表在插入和删除上比较有优势。主要功能是向消息池投递消息( messagequeue.enqueuemessage)和取走消息池的消息( messagequeue.next)。
- handler:消息辅助类,主要功能是向消息池发送各种消息事件( handler.sendmessage)和处理相应消息事件( handler.handlemessage);
- looper:消息控制器,不断循环执行( looper.loop),从messagequeue中读取消息,按分发机制将消息分发给目标处理者。
从上面的类图可以看出:
- looper有一个messagequeue消息队列;
- messagequeue有一组待处理的message;
- message中记录发送和处理消息的handler;
- handler中有looper和messagequeue。
messagequeue、handler和looper三者之间的关系: 每个线程中只能存在一个looper,looper是保存在threadlocal中的。 主线程(ui线程)已经创建了一个looper,所以在主线程中不需要再创建looper,但是在其他线程中需要创建looper。 每个线程中可以有多个handler,即一个looper可以处理来自多个handler的消息。 looper中维护一个messagequeue,来维护消息队列,消息队列中的message可以来自不同的handler。
handler的运行流程
在子线程执行完耗时操作,当handler发送消息时,将会调用 messagequeue.enqueuemessage,向消息队列中添加消息。 当通过 looper.loop开启循环后,会不断地从消息池中读取消息,即调用 messagequeue.next, 然后调用目标handler(即发送该消息的handler)的 dispatchmessage方法传递消息, 然后返回到handler所在线程,目标handler收到消息,调用 handlemessage方法,接收消息,处理消息。
源码分析
在子线程创建handler
class looperthread extends thread { public handler mhandler; public void run() { looper.prepare(); mhandler = new handler() { public void handlemessage(message msg) { // process incoming messages here } } ; looper.loop(); } }
从上面可以看出,在子线程中创建handler之前,要调用 looper.prepare()
方法,handler创建后,还要调用 looper.loop()
方法。而前面我们在主线程创建handler却不要这两个步骤,因为系统帮我们做了。
主线程的looper
在activitythread的main方法,会调用
looper.preparemainlooper()
来初始化looper,并调用looper.loop()
方法来开启循环。
public final class activitythread extends clienttransactionhandler { // ... public static void main(string[] args) { // ... looper.preparemainlooper(); // ... looper.loop(); } }
looper
从上可知,要使用handler,必须先创建一个looper。
初始化looper:
public final class looper { public static void prepare() { prepare(true); } private static void prepare(boolean quitallowed) { if (sthreadlocal.get() != null) { throw new runtimeexception("only one looper may be created per thread"); } sthreadlocal.set(new looper(quitallowed)); } public static void preparemainlooper() { prepare(false); synchronized (looper.class) { if (smainlooper != null) { throw new illegalstateexception("the main looper has already been prepared."); } smainlooper = mylooper(); } } private looper(boolean quitallowed) { mqueue = new messagequeue(quitallowed); mthread = thread.currentthread(); } // ... }
从上可以看出,不能重复创建looper,每个线程只能创建一个。创建looper,并保存在 threadlocal
。其中threadlocal是线程本地存储区(thread local storage,简称tls),每个线程都有自己的私有的本地存储区域,不同线程之间彼此不能访问对方的tls区域。
开启looper
public final class looper { // ... public static void loop() { // 获取tls存储的looper对象 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; // 进入loop主循环方法 for (;;) { message msg = queue.next(); // 可能会阻塞,因为next()方法可能会无线循环 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 final printer logging = me.mlogging; if (logging != null) { logging.println(">>>>> dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } // ... final long dispatchstart = needstarttime ? systemclock.uptimemillis() : 0; final long dispatchend; try { // 获取msg的目标handler,然后分发message msg.target.dispatchmessage(msg); dispatchend = needendtime ? systemclock.uptimemillis() : 0; } finally { if (tracetag != 0) { trace.traceend(tracetag); } } // ... msg.recycleunchecked(); } } }
handler
创建handler:
public class handler { // ... public handler() { this(null, false); } public handler(callback callback, boolean async) { // ... // 必须先执行looper.prepare(),才能获取looper对象,否则为null mlooper = looper.mylooper(); if (mlooper == null) { throw new runtimeexception( "can't create handler inside thread " + thread.currentthread() + " that has not called looper.prepare()"); } mqueue = mlooper.mqueue; // 消息队列,来自looper对象 mcallback = callback; // 回调方法 masynchronous = async; // 设置消息是否为异步处理方式 } }
发送消息:
子线程通过handler的post()方法或send()方法发送消息,最终都是调用
sendmessageattime()
方法。
post方法:
public final boolean post(runnable r){ return sendmessagedelayed(getpostmessage(r), 0); } public final boolean postattime(runnable r, long uptimemillis){ return sendmessageattime(getpostmessage(r), uptimemillis); } public final boolean postattime(runnable r, object token, long uptimemillis){ return sendmessageattime(getpostmessage(r, token), uptimemillis); } public final boolean postdelayed(runnable r, long delaymillis){ return sendmessagedelayed(getpostmessage(r), delaymillis); } private static message getpostmessage(runnable r) { message m = message.obtain(); m.callback = r; return m; }
send方法:
public final boolean sendmessage(message msg){ return sendmessagedelayed(msg, 0); } public final boolean sendemptymessage(int what){ return sendemptymessagedelayed(what, 0); } public final boolean sendemptymessagedelayed(int what, long delaymillis) { message msg = message.obtain(); msg.what = what; return sendmessagedelayed(msg, delaymillis); } public final boolean sendemptymessageattime(int what, long uptimemillis) { message msg = message.obtain(); msg.what = what; return sendmessageattime(msg, uptimemillis); } 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); } private boolean enqueuemessage(messagequeue queue, message msg, long uptimemillis) { msg.target = this; if (masynchronous) { msg.setasynchronous(true); } return queue.enqueuemessage(msg, uptimemillis); }
分发消息
在loop()方法中,获取到下一条消息后,执行
msg.target.dispatchmessage(msg)
,来分发消息到目标handler。
public class handler { // ... public void dispatchmessage(message msg) { if (msg.callback != null) { // 当message存在回调方法,调用该回调方法 handlecallback(msg); } else { if (mcallback != null) { // 当handler存在callback成员变量时,回调其handlemessage()方法 if (mcallback.handlemessage(msg)) { return; } } // handler自身的回调方法 handlemessage(msg); } } private static void handlecallback(message message) { message.callback.run(); } }
总结
到此这篇关于深入理解android消息机制handler的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持。