Handler机制和源码详解

       在网上看了侃哥的视频,详细记录一下.

        对Handler机制的理解,可以分成四个部分,消息的创建,Handler的创建,消息的发送,消息的处理。

        源码基本上都是基于2.3的源码(相对比较好理解),部分会做一下比较。


1、消息的创建  handler调用obtainMessage

   
   
public final Message obtainMessage()
{
    // 这个this就是handler
         return Message.obtain(this);
}
    
    
 //其实消息还是Message自己创建的
public static Message obtain(Handler h) {
// 调用自身的obtain方法
Message m = obtain();
// 同时将targer指向handler 其他重载方法也是一样
m.target = h;
 
return m;
}

   
   
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
// 如果有消息 直接赋给m 没有的话 创建一个新的消息
Message m = sPool;
// Message内部自己维护消息
sPool = m.next;
m.next = null;
sPoolSize--;
return m;
}
}
return new Message();
}
    Message内部有一个成员属性:next
          假如有ABC三条消息,那么A会先处理,A.next指向B,B.next指向C
          就像一个单链表。
    sPool指向了消息池中的第一条消息(sPool就是一个消息,不过名字叫Pool(池)),如果把sPool赋值给m,那么B就变成了第一条消息(sPool=m.next;),同时A.next就没有指向了,然后sPoolSize数量减一,这个size的最大值是50。(循环的部分还没看懂)
   
   
  // recycleUnchecked()方法
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}

2、创建Handler
构造函数 内部封装了Looper和MQ   创建Handler的时候会拿到当前线程的Looper和MQ,如果没有就会报错。
   
   
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
// 从Looper对象中获取,所以使用Handler必须要先有Looper  
// 在prepare方法中,会判断有没有looper绑定到当前线程,没有的话 new一个
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;
}
    
    
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}

3、Looper.prepare ---->确保线程中有一个looper对象和消息队列对象
  
  
// 2.3 源码中有无参的构造函数  新的似乎被隐藏了
private Looper() {
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}
   
   
private static void prepare(boolean quitAllowed) {
// 如果已经执行过prepare方法,那么会报异常,
// 没有的话 创建一个 new Looper 并绑定到当前线程 此时线程中就有了一个Loooer对象
// 参见构造函数
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 2.3的源码构造函数是没有参数的 5.1源码,隐藏了构造函数
// 但肯定还是基于2.3源码的 Looper初始化的时候,有一个消息队列对象
sThreadLocal.set(new Looper(quitAllowed));
}

4、主线程在启动的时候,ActivityThread会调用Looper.prepareMainLooper()
     注意: ActivityThread不是Thread的子类,就是一个类,有main方法,也就是我们的主线程
     一个程序如果没有死循环,那么运行完就应该结束了。程序如果不退出就应该一直运行,所以应该要有一个死循环(加上阻塞设置,可以节省资源)
   
   
public final class ActivityThread
main方法
   
   
public static final void main(String[] args) {
SamplingProfilerIntegration.start();
 
Process.setArgV0("<pre-initialized>");
 
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
 
ActivityThread thread = new ActivityThread();
thread.attach(false);
 
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
 
Looper.loop();
 
if (Process.supportsProcesses()) {
throw new RuntimeException("Main thread loop unexpectedly exited");
}
 
thread.detach();
String name = (thread.mInitialApplication != null)
? thread.mInitialApplication.getPackageName()
: "<unknown>";
Slog.i(TAG, "Main thread of " + name + " is now exiting");
}
}

5、创建之后,使用Handler发送消息  最终都会调用sendMessageAtTime 将消息插入到消息队列
  
  
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
//msg的 when
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
   
   
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);
    }  
6、MessageQueue中的enqueueMessage方法
   
   
boolean enqueueMessage(Message msg, long when) {
// when --》 数值越小 越靠前
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
 
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
msg.recycle();
return false;
}
 
msg.markInUse();
msg.when = when;
// mMessages 消息队列里的第一条消息
Message p = mMessages;
boolean needWake;
// 如果消息队列里的第一条消息为null 或者。。。那么发过来的就是第一条消息 同时next只能等于null
// 第二种情况:时间如果是0,说明消息需要优先处理,同样将发过来的消息放在第一条,而 msg.next = p;就把传入的msg的next设置为原来的第一条( Message p = mMessages;
// 第三种情况:传入消息的时间,小于第一条消息的时间,仍然要优先运行。
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;
// 2.3 的源码是用while()
for (;;) {
// prev指向第一条 p指向下一条
prev = p;
p = p.next;
// 如果没有下一条或者时间小于下一条的时间 跳出(顺序正确) 换下一条 没有下一条 跳出
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
// 是否需要唤醒主线程 通常第一条才(可能)需要(也需要一些运算) 不是第一条就不用
needWake = false;
}
}
// 跟消息队列的消息比较 找到传入消息对应的插入位置
// 例如队列里有ABC 三条消息, 假设都是按顺序的,那么当p走到C的时候,根据上面prev=p p=p.next的时候,
// prev 就是C C.next是null 跳出 那么传入的消息就插在最后,C的.next指向传入的消息
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;
}
2.3的排队方法
    
    
final boolean enqueueMessage(Message msg, long when) {
if (msg.when != 0) {
throw new AndroidRuntimeException(msg
+ " This message is already in use.");
}
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
final boolean needWake;
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}
 
msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked; // new head, might need to wake up
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
needWake = false; // still waiting on head, no need to wake up
}
}
if (needWake) {
nativeWake(mPtr);
}
return true;
}

MessageQueue中有几个本地方法
   
   
private native static long nativeInit();
private native static void nativeDestroy(long ptr);
private native static void nativePollOnce(long ptr, int timeoutMillis);
private native static void nativeWake(long ptr);
private native static boolean nativeIsIdling(long ptr);
指向AndroidSource_GB\frameworks\base\core\jni  android_os_MessageQueue.cpp
   
   
static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {
NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
if (! nativeMessageQueue) {
jniThrowRuntimeException(env, "Unable to allocate native queue");
return;
}
// 返回值?  
android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
}
             static void android_os_MessageQueue_setNativeMessageQueue(JNIEnv* env, jobject messageQueueObj, NativeMessageQueue* nativeMessageQueue) {
                   env->SetIntField(messageQueueObj, gMessageQueueClassInfo.mPtr, reinterpret_cast<jint>(nativeMessageQueue));
                }
    
    
static void android_os_MessageQueue_nativeDestroy(JNIEnv* env, jobject obj) {
NativeMessageQueue* nativeMessageQueue =
android_os_MessageQueue_getNativeMessageQueue(env, obj);
if (nativeMessageQueue) {
android_os_MessageQueue_setNativeMessageQueue(env, obj, NULL);
delete nativeMessageQueue;
}
}
     
     
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) {
// reinterpret_cast是一个强类型指针,将整形转化成指针 ptr在MessageQueue中 是通过nativeInit()得到的
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
return nativeMessageQueue->wake();
}
// 指向了wake方法
   
   
class NativeMessageQueue {
public:
NativeMessageQueue();
~NativeMessageQueue();
 
inline sp<Looper> getLooper() { return mLooper; }
 
void pollOnce(int timeoutMillis);
void wake();
 
private:
sp<Looper> mLooper;
};
    
    
NativeMessageQueue::NativeMessageQueue() {
mLooper = Looper::getForThread();
if (mLooper == NULL) {
mLooper = new Looper(false);
Looper::setForThread(mLooper);
}
}
 
NativeMessageQueue::~NativeMessageQueue() {
}
 
void NativeMessageQueue::pollOnce(int timeoutMillis) {
mLooper->pollOnce(timeoutMillis);
}
 
void NativeMessageQueue::wake() {
mLooper->wake();
}
指向了Looper的wake方法,也就是下面Looper.cpp的wake方法,往管道中写入了一个 “w”;
looper.cpp中的wake方法 2.3源码AndroidSource_GB\frameworks\base\libs\utils
   
   
 
void Looper::wake() {
#if DEBUG_POLL_AND_WAKE
LOGD("%p ~ wake", this);
#endif
#ifdef LOOPER_STATISTICS
// FIXME: Possible race with awoken() but this code is for testing only and is rarely enabled.
if (mPendingWakeCount++ == 0) {
mPendingWakeTime = systemTime(SYSTEM_TIME_MONOTONIC);
}
#endif
ssize_t nWrite;
do {
// 写了一个W 到管道中 用于唤醒主线程
nWrite = write(mWakeWritePipeFd, "W", 1);
} while (nWrite == -1 && errno == EINTR);
if (nWrite != 1) {
if (errno != EAGAIN) {
LOGW("Could not write wake signal, errno=%d", errno);
}
}
}

7、消息处理 使用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();
// 2.3的源码这里是while(true)  
for (;;) {
// linux底层采用epoll的方式 等待唤醒
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 就是发送该消息的handler
// 线程中可以有多个Handler,使用绑定的target就可以保证,是哪个Handler发送的消息
// 就由哪个Handler处理
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();
}
}     
         如果线程不是死循环--->那么运行完就结束了。。。
        

8、dispatchMessage方法
   
   
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
// 如果使用了post(Runnable r)的话 会将r绑定在一个消息上发送 callback就有值,callback就是一个Runnable
if (msg.callback != null) {
handleCallback(msg);
} else {
// handler内部封装了一个接口 Callback 不过看起来只在Handler的隐藏构造方法中赋值,所以一般为空
// 为空的话,就调用复写的handlerMessage方法
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
// 需要复写的方法
handleMessage(msg);
}
}
    
    
/**
* Callback interface you can use when instantiating a Handler to avoid
* having to implement your own subclass of Handler.
*
* @param msg A {@link android.os.Message Message} object
* @return True if no further handling is desired
*/
public interface Callback {
public boolean handleMessage(Message msg);
}

总结:
1、消息实际有Message自己创建,从sPool中获取,没有的话,new一个
        2、Handler创建时,会拿到当前线程的Looper,所以必须要有Looper对象,然后从Looper中按到MQ
        3、Looper.prepare(),会将Looper绑定到当前线程,没有的话,new Looper
        4、new Looper的时候 构造中会new一个MQ
        5、消息发送时,拿到Looper和MQ,调用MQ的方法对消息进行排队(根据是否为空,以及发送时间,将消息插入到合适位置)。
        6、如果当前消息是第一条,那么判断是否唤醒主线程,执行对消息的处理。
        7、使用loop方法,获取到消息,并使用绑定在msg上的handler进行dispatchMessage(); 最终会调用handleMessage();    
大致流程如上,底层的部分还是不是非常理解,如有错误之处,还请指正。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值