Handler源码认知

Posted 夜宿山寺

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Handler源码认知相关的知识,希望对你有一定的参考价值。

Handler是面试一定会问得机制,每次都能够打上来,但是答的很浅,只是说了大概的一个工作机制,画了个图从源码的角度加深自己的理解吧。首先上图





上面是大概的一个工作机制,从源码的角度来说其实没有太多重要的地方,主要就关注这么几个类

Message:承载着消息的对象。

MessageQueue:存放消息的队列

Handler:负责发送消息和接收消息的对象

Looper:消息循环机制

通常都会使用消息池机制,如下可以获得一个Message对象

Message.obtain(this)obtain()
message.sendToTarget();


Message message = handler.obtainMessage();
//从源码的角度来说其实在里面做了那么一件事情,它会把当前的那个handler传进来,到之后后面的message可以直接调用
//message.sendToTarget();

public static Message obtain(Handler h) 
        Message m = obtain();
        m.target = h;

        return m;
    
在obtain这个方法里面又干了这么一件事情
  public static Message obtain() 
        synchronized (sPoolSync) 
            if (sPool != null) 
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            
        
        return new Message();
    
//看看就能够知道了,第一次创建的时候是没有消息池的,直接new 了一个对象出去,在后面会把该消息放入消息池
//这里完成了消息的初始化,当执行完自己的逻辑之后调用message.sendToTarget();通过保存在message内部的
//handler发送消息到消息池里面
   boolean enqueueMessage(Message msg, long 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;
            Message p = mMessages;
            boolean needWake;
            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的理解


以上是关于Handler源码认知的主要内容,如果未能解决你的问题,请参考以下文章

Handler与异步消息处理

Handler与异步消息处理

Android消息机制之Handler

Handler源码分析

Handler源码分析

Android Handler消息机制源码解析