Handler:源码分析

1、核心类

注: 表格属性 rowspan colspan

类名核心方法作用
处理器 Handler sendMessage(Message msg)将消息发送到消息队列
post(Runnable r)
dispatchMessage(Message msg)将消息分发给对应Handler
handleMessage(Message msg)处理对应消息
消息队列 MessageQueueenqueueMessage(Message msg, long when)将消息根据时间添加到消息队列
Message next()从消息队列移出消息
循环器 Looperprepare()为当前线程创建一个 Looper 对象和一个 MessageQueue 对象
loop()消息循环从消息队列中取出消息发送给Handler,无消息则阻塞
2、源码分析
  1. Android 应用程序启动时,会创建 1 个主线程(ActivityThread),自动调用 main() 方法。
  2. main() 方法中为主线程创建 1 个 Looper 对象 同时创建 Looper 的 MessageQueue 对象。
  3. 主线程中创建 Handler 为其指定主线程的 Looper 对象和 MessageQueue 对象。
  4. 子线程中创建 Handler 需要手动创建子线程的 Looper 对象和 MessageQueue 对象(及手动调用 Looper.prepare() )。才能创建 Handler 。
	// ActivityThread.class
	
	// 应用程序启动执行 main() 方法。
    public static void main(String[] args) {
        // 1、为主线程创建 1 个 Looper 对象
        Looper.prepareMainLooper();
        
		// 2、创建主线程
        ActivityThread thread = new ActivityThread();
        
        // 3、开启消息循环
        Looper.loop();
    }
	// ThreadLocal.class

    // 获取当前线程的 Looper 对象
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

// 设置本地线程变量到 ThreadLocalMap ,键 this(ThreadLocal 对象),值 Looper 对象(调用 Looper 的 prepare() 时创建)。
    private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }
	// Looper.class
	
	//  为主线程创建 1 个 Looper 对象
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
    
    //  为子线程创建 1 个 Looper 对象
    public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
    	// 1、当前线程 Looper 不为 null 抛出异常,及 Looper.prepare() 方法不能调用2次。ThreadLocal 存储本地线程变量。
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

    private Looper(boolean quitAllowed) {
    	// 1、创建 1 个 Looper,指定 1 个 消息队列(MessageQueue)。
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

	// 获取当前线程的 Looper 对象
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }
    
    // 消息循环
    public static void loop() {
    	// 1.获取当前线程 Looper。
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        // 2.获取消息队列
        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();

        // Allow overriding a threshold with a system prop. e.g.
        // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start'
        final int thresholdOverride =
                SystemProperties.getInt("log.looper."
                        + Process.myUid() + "."
                        + Thread.currentThread().getName()
                        + ".slow", 0);

        boolean slowDeliveryDetected = false;		
        
		// 3.消息循环。
        for (;;) {
        	// 3.1、消息队列取出消息,消息为空则线程阻塞。
            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
            final Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;

            final long traceTag = me.mTraceTag;
            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }
            final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            final long end;
            try {
            	// 3.2、分发消息给对应的 Handler(target 即 Handler)。
                msg.target.dispatchMessage(msg);
                end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            if (slowDispatchThresholdMs > 0) {
                final long time = end - start;
                if (time > slowDispatchThresholdMs) {
                    Slog.w(TAG, "Dispatch took " + time + "ms on "
                            + Thread.currentThread().getName() + ", h=" +
                            msg.target + " cb=" + msg.callback + " msg=" + msg.what);
                }
            }

            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);
            }
			// 3.3、释放消息。
            msg.recycleUnchecked();
        }
    }
	// MessageQueue.class
	
	// next() 方法,从消息队列取出消息。
    Message next() {
        // Return here if the message loop has already quit and been disposed.
        // This can happen if the application tries to restart a looper after quit
        // which is not supported.
        final long ptr = mPtr;
        if (ptr == 0) {
            return null;
        }

        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
			 // 1、nextPollTimeoutMillis 为 -1 消息队列处于等待状态。
            nativePollOnce(ptr, nextPollTimeoutMillis);
			// 2、synchronized  保证多线程安全。
            synchronized (this) {
                // Try to retrieve the next message.  Return if found.
                final long now = SystemClock.uptimeMillis();
                Message prevMsg = null;
                Message msg = mMessages;
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }
                // 3、根据时间从消息队列取消息。
                if (msg != null) {
                    if (now < msg.when) {
                        // Next message is not ready.  Set a timeout to wake up when it is ready.
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
                        mBlocked = false;
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
                            mMessages = msg.next;
                        }
                        msg.next = null;
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    // 消息队列中已无消息,则将 nextPollTimeoutMillis 设为-1 下次循环时,消息队列则处于等待状态。
                    nextPollTimeoutMillis = -1;
                }

                // Process the quit message now that all pending messages have been handled.
                if (mQuitting) {
                    dispose();
                    return null;
                }

                // If first time idle, then get the number of idlers to run.
                // Idle handles only run if the queue is empty or if the first message
                // in the queue (possibly a barrier) is due to be handled in the future.
                if (pendingIdleHandlerCount < 0
                        && (mMessages == null || now < mMessages.when)) {
                    pendingIdleHandlerCount = mIdleHandlers.size();
                }
                if (pendingIdleHandlerCount <= 0) {
                    // No idle handlers to run.  Loop and wait some more.
                    mBlocked = true;
                    continue;
                }

                if (mPendingIdleHandlers == null) {
                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
                }
                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
            }

            // Run the idle handlers.
            // We only ever reach this code block during the first iteration.
            for (int i = 0; i < pendingIdleHandlerCount; i++) {
                final IdleHandler idler = mPendingIdleHandlers[i];
                mPendingIdleHandlers[i] = null; // release the reference to the handler

                boolean keep = false;
                try {
                    keep = idler.queueIdle();
                } catch (Throwable t) {
                    Log.wtf(TAG, "IdleHandler threw exception", t);
                }

                if (!keep) {
                    synchronized (this) {
                        mIdleHandlers.remove(idler);
                    }
                }
            }

            // Reset the idle handler count to 0 so we do not run them again.
            pendingIdleHandlerCount = 0;

            // While calling an idle handler, a new message could have been delivered
            // so go back and look again for a pending message without waiting.
            nextPollTimeoutMillis = 0;
        }
    }

	// enqueueMessage(Message msg, long when) 方法,将消息插入到消息队列。采用单链表提高插入、删除消息的效率 。
    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(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            // 1.消息队列无消息:将当前消息插入到对头;消息处于等待状态,则唤醒
            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.消息队列有消息:则根据消息创建时间插入到队列。
                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;
    }
	// Message.class
	
	// 从消息池获取消息对象,默认缓存50个消息对象,避免每次 new Message() 重新分配内存;消息池没有可用消息采用 new Message()。
    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();
    }
	// Handler.class
	
    public Handler() {
        this(null, false);
    }
    
	// 创建 Handler 对象。
    public Handler(Callback callback, boolean async) {
		// 1、指定 Looper 对象
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        // 2、指定消息队列对象(MessageQueue)
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

	// 分发处理消息的方法。
    public void dispatchMessage(Message msg) {
    	// 1.msg.callback (即 runnable) 不为空,表示采用 post(Runnable r) 发送消息,回调重写的 run() 方法。
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            // 2.msg.callback (即 runnable) 为空,表示采用 sendMessage(Message msg) 发送消息,回调重写的 handleMessage(Message msg) 方法。
            handleMessage(msg);
        }
    }
	
	// 采用 post 方式最终回调 Runnable 的 run() 方法
    private static void handleCallback(Message message) {
        message.callback.run();
    }

	// 采用 sendMessage(Message msg) 发送消息。
    public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

	// sendMessage/post 方式开始走相同的流程。
    public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        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) {
    	// 1.msg.target 赋值为 this(当前 Handler)。
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        // 2.消息放入消息队列。
        return queue.enqueueMessage(msg, uptimeMillis);
    }

	// 采用 post(Runnable r) 发送消息。
    public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

    private static Message getPostMessage(Runnable r) {
    	// 1.创建一个消息对象。
        Message m = Message.obtain();
        // 2.m.callback 赋值为 r(Runnable)。
        m.callback = r;
        return m;
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值