Handler典型使用方法代码分析
- 典型的Handler的使用方法
Looper.prepared();
Handler handler = new Handler();
Looper.loop();
- Handler 初始化和消息处理流程
- Looper的初始化
Class Looper {
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static void prepare(boolean quitAllowed) {
sThreadLocal.set(new Looper(quitAllowed));
}
}
private Looper(boolean quitAllowed) {
//创建Native层的一个Looper
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
首次建立一个Looper并且将这个Looper与当前Thread连接
- Looper的底层实现
Native层的Looper开始于MessageQueue.nativeInit()
static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {
//创建Native层的MessageQueue
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
}
NativeMessageQueue::NativeMessageQueue() :
mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {
//调用Native层的Looper
mLooper = Looper::getForThread();
//第一次调用的话,这里的mLooper应该是空的,所以应该从创建一个新的Looper
if (mLooper == NULL) {
mLooper = new Looper(false);
//这里面新建的Looper与当前Thread绑定
Looper::setForThread(mLooper);
}
}
Looper::Looper(bool allowNonCallbacks) :
mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),
mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),
mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
//首先建立一个fd,用来从epoll中唤醒
mWakeEventFd = eventfd(0, EFD_NONBLOCK);
LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd. errno=%d", errno);
AutoMutex _l(mLock);
rebuildEpollLocked();
}
void Looper::rebuildEpollLocked() {
// Allocate the new epoll instance and register the wake pipe.
//创建epoll,并且制定epoll大小为8,也就是最多监视8个fd
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
struct epoll_event eventItem;
memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
eventItem.events = EPOLLIN;
eventItem.data.fd = mWakeEventFd;
//首先将mWakeEventFd注册进去
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);
}
简单来说就是将这个mWakeEventFd放入到epoll中。
- Handler 初始化
public Handler(Callback callback, boolean async) {
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;
}
就是将Looper中的Queue放入到handler中的mQueue对象中。
- Looper运行
public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
for (;;) {
Message msg = queue.next(); // might block
msg.target.dispatchMessage(msg);//看到这里处理消息的时候是调用target的dispatchMessage。所以在一个looper对应多个handler的时候不会混乱
msg.recycleUnchecked();
}
}
Message next() {
for (;;) {
nativePollOnce(ptr, nextPollTimeoutMillis);
}
}
这个函数最终会调用到Looper.c中的pollOnce函数。在pullInner中会阻塞在epoll_wait,直到mEpollFd监听的文件描述符有可操作的属性。
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
result = pollInner(timeoutMillis);
}
int Looper::pollInner(int timeoutMillis) {
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis)
for (int i = 0; i < eventCount; i++) {
int fd = eventItems[i].data.fd;
uint32_t epollEvents = eventItems[i].events;
if (fd == mWakeEventFd) {
if (epollEvents & EPOLLIN) {//如果是mWakeEventFd的话就唤醒这个loop
awoken();
} else {
}
} else {
//获取对应的event,并且将event放入到reponse队列中。
}
}
}
- Handler 消息的发送
其实Handler的发送消息最终都是调用enqueueMessage
- Message的发送过程
下面看其中的一个函数为例
sendMessage(Message msg)->sendMessageDelayed(Message msg, long delayMillis)->sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis)->enqueueMessage(queue, msg, uptimeMillis)
- Runnable类型Msg发送过程
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
发送Runnable给handlerjiushi将这个runnable添加到callback中。之后的处理流程和普通的Message的处理方式就一样了。
既然所有的Message最终都会调用enqueueMessage,将Message添加到Queue中,那么接下来看一下enqueueMessage是怎么实现的
- enqueueMessage的实现
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;//注意这里面将this赋值给target,之后在处理消息的时候会用到
return queue.enqueueMessage(msg, uptimeMillis);
}
原来就是调用queue的enqueueMessage。
这个对应MessageQueue.enqueueMessage()
boolean enqueueMessage(Message msg, long when) {
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插入到队列中
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;
}
这里需要注意的是,只有调用nativeWake这个函数之后,loop才能离开block状态,之后才能处理msg。
上面再介绍Looper.loop()函数的时候在调用handler.dispatchMessage()函数。这里还有一点需要注意的。
看下这个函数的实现
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,这种情况实际上就是这个Message是一个Runnable
2.初始化Handler时传入的callback。目前这种使用方法还没看到过。但是在这个callback中可以实现记录Handler处理了哪些消息。
3.Handler的handleMessage函数