Android Handler
来源:互联网 发布:威纶触摸屏数据导出 编辑:程序博客网 时间:2024/06/16 20:33
一点点更新吧
Handler
在android中,每个thread有一个messageQueue,handler负责deliver message和execute message
deliver message的方法又sendMessage, sendMessageDelayed, sendMessageAtTime,sendMessageAtFrontOfQueue,但最终都会调用handler.enqueue方法,如下源码:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis);}
可以看到,在这里,message的target被设为当前的handler,后边在Looper.loop方法中会看到msg.target.dispatchMessage(msg)的调用,此处的target就是handler实例。
第2,3行是设置message是否是asynchronous异步的。
最后一行是调用MessageQueue.enqueueMessage(msg,uptimeMillis)
下面是MessageQueue.enqueueMessage的源码:
boolean enqueueMessage(Message msg, long when) {
//每个message必须有一个target,即handler if (msg.target == null) { throw new IllegalArgumentException("Message must have a target."); }
//message正在被使用 if (msg.isInUse()) { throw new IllegalStateException(msg + " This message is already in use."); } synchronized (this) {
//messageQueue执行了quit,不再进行消息处理 if (mQuitting) { IllegalStateException e = new IllegalStateException( msg.target + " sending message to a Handler on a dead thread"); Log.w("MessageQueue", e.getMessage(), e);
//message重置,以便再利用,Message.Obtain() msg.recycle(); return false; }
msg.markInUse(); msg.when = when; Message p = mMessages; boolean needWake;
//将message压入queue 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;}
上面简述了handler.enqueque()的方法,下面是说说handler.dispatchMessage()方法:
/** * Handle system messages here. */public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}
代码很简单直观:
1. 如果message有callback,则调用handleCallback(msg),进而调用message.callback.run(),这需要创建message时写好callback方法。如下:
private static void handleCallback(Message message) { message.callback.run();}
2. 如果message没有callback,
2.1. 但是handler的mCallback参数不为空,则调用mCallback.handleMessage()。Callback是接口,需要重写handleMessage方法,如下:
public interface Callback { public boolean handleMessage(Message msg);}
2.2 handler的mCallback参数为空,调用handler的handleMessage方法,该需要重写:
/** * Subclasses must implement this to receive messages. */public void handleMessage(Message msg) {}
所以我们初始化handler的时候可以使用两种方法(实际有很多种,只举两种我常用的例子),注意两个handleMessage方法的返回值类型不同,一个boolean一个void:
Handler mHandler = new Hander(new Callback(){
@Override
public bolean handleMessage(Message msg){
//TODO
}
})
Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg){
//TODO
}
}
Looper
提到handler必不可少的要说Looper。Looper,顾名思义,就是用来做循环的,它可以对MessageQueue进行循环(loop()方法)。每个Thread都要有一个Looper,否则无法接收Message。
Looper有几个重要的方法:
prepare(),loop(),quit()。
prepare(),初始化,必须要做,且只能执行月hi次
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the 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(); }}
- android Handler
- android Handler
- android Handler
- android Handler
- Android Handler
- android---handler
- android-handler
- Android Handler
- Android Handler
- Android Handler
- android Handler
- android--Handler
- Android Handler
- Android Handler
- Android Handler
- Android Handler
- Android handler
- Android Handler
- day14_Regex
- Leetcode 146. LRU Cache
- Hystrix系列-5-Hystrix的资源隔离策略
- java集合框架之Set集合实现类性能对比
- JavaScript DOM基本操作
- Android Handler
- kvm : disabled by bios 问题解决
- Tiny_cnn用自己的数据训练和测试
- 1369: [Baltic2003]Gem
- ZeroMQ在Win7下的编译
- AndroidFlux
- 小米-懂二进制 华为-最高分是多少
- Quartz任务调度(4)JobListener分版本超详细解析
- 消息队列应用场景