android开发教程之Handler分析
程序员文章站
2022-05-07 22:07:26
handler
handler的应用场景
handler是android中常用的异步处理机制。常用于处理线程内任务的同步处理和线程间的通信,例如当子线程中执行任务引起需要刷新u...
handler
handler的应用场景handler是android中常用的异步处理机制。常用于处理线程内任务的同步处理和线程间的通信,例如当子线程中执行任务引起需要刷新ui时在子线程中通过主线程的handler发送消息通知ui刷新。 handler的基本用法
handler handler = new handler() { @override handlemessage(message msg) { // 处理消息 } } new thread(new runnable(){ @override public void run() { message msg = message.obtin(); msg.what = cmd; handler.sendmessage(msg); } }).start();handler的分析
handler的运行过程实际上就是在线程中通过一个循环任务不停从消息队列中读取消息并处理的过程。发送消息实际上就是往消息队列中投入消息。
处理消息的调度者——looper
handler 在初始化时默认使用主线程的looper,主线程的looper一直在循环读取成员变量中的messagequeue,读取到message就使用与之绑定的handler处理
/* looper.java */ public static void loop() { …… for (;;) { message msg = queue.next(); // 阻塞读取队列中的message if (msg == null) { // no message indicates that the message queue is quitting. return; } …… try { msg.target.dispatchmessage(msg); //交给对应handler的处理 end = (slowdispatchthresholdms == 0) ? 0 : systemclock.uptimemillis(); } finally { if (tracetag != 0) { trace.traceend(tracetag); } } …… msg.recycleunchecked(); } }
- 消息的发送 handler的sendmessage方法最终会调用messagequeue的enqueuemessage方法将message投入队列中,并且在投入队列之前将需要处理的handler与message绑定。
/* handler.java */ 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); }
- 消息的通道——messagequeue 实现了一个缓存消息的先入先出队列
boolean enqueuemessage(message msg, long when) { …… synchronized (this) { …… /* messagequeue管理数据实际是一个单向链表,mmessages作为这个链表的头,enqueuemessage传入的message总是放在最后 */ 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; } …… } return true; }