Handler典型使用方法代码分析

  • 典型的Handler的使用方法
Looper.prepared();
Handler handler = new Handler();
Looper.loop();

 

  • Handler 初始化和消息处理流程

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典型使用方法代码分析

  • 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函数