public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
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 loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue; 获取到looper绑定的消息队列
......
for ( ;; ) {
Message msg = queue.next(); // 如果当前队列为空,则阻塞队列,na因为next是syn同步块
if (msg == null) {//如果对象为空直接退出
return;
}
......
msg.target.dispatchMessage(msg); //核心:通过dispatchMessage(msg)分发消息;
......
msg.recycleUnchecked(); //清空对象中的字段
}
}
第一步:new handler的时候拿到当前线程的looper对象和looper绑定的MessageQueue对象。
public Handler(Callback callback, boolean async) {
......
mLooper = Looper.myLooper();
......
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
第二步:提交msg的方法:所有的sendMessage最终都是调用sendMessageAtTime(msg,time)方法,然后将handler实例对象封装到msg对象中,通过queue.enqueueMessage()方法入队。
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
........
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
........
return queue.enqueueMessage(msg, uptimeMillis);
}
第三步:通过dispatchMessage方法对收到的消息进行分发;
vpublic void dispatchMessage(Message msg) {
if (msg.callback != null) { //如果Message中封装了callback方法
handleCallback(msg);
} else {
if (mCallback != null) { //如果new handler的时候传入了callback方法
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg); // 如果在handler中重写了handleMessage方法
}
}
消息对象,其中的target是用来绑定handler的,数据结构是栈结构,先进后出
方法一:Message.obtin() ,入栈操作。先 复用Message,没有在创建一个。
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0;
sPoolSize--;
return m;
}
}
return new Message();
}
方法二: recycle(),清空并入栈
void recycleUnchecked() {
flags = FLAG_IN_USE;
清空数据。。。
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
Looper.prepare() —> new Looper(boolen) —> new MessageQueue(boolen) —> int nativeInit() 由native层创建一个native层的MessageQueue队列,将地址返回存在java层。
消息入队方法:
boolen enqueueMessage(msg , time) :通过synchronized(this)阻塞,通过判断比较time,根据time的先后顺序入队。
消息出队方法:
Message next():根据msg中的when阻塞队列的等待时间。通过.next判断是否有下一个,依次获取。
阻塞方法:
nativePollOnce() —> nativeMessageQueue.pollOnce() —> 底层MessageQueue中的looper对象中的pollOnce(timeoutMillis) —> pollInner(timeoutMillis) —> int eventCount = epoll_wait()
Java层的阻塞是通过native层的epoll机制来实现的因此looper死循环不会造成UI阻塞。阻塞结果三种:eventCount <0:错误返回;eventCount =0:超时返回;eventCount > 0消息事件返回。
Linux来说一切皆文件。Epoll机制有三个方法,epoll_create()、epoll_ctl()、epoll_wait();
触发机器也就是通知机制,分两种:水平触发(level-triggered)+边缘触发(edge-triggered)。
level-triggered:当缓存区中数据由空变不空时,将触发可读信号,直到读完为止;当缓存区中数据由满变为不满时,将触发可写信号,直到写满为止。
edge-triggered:当缓存区中数据由空变不空时,将触发可读信号一次,程序将执行轮询读操作,直到读到EGAIN为止;当缓存区中数据由满变为不满时,将触发可写信号一次,程序将执行轮询写操作。