handler机制主要流程分析

815 阅读2分钟

handler

主要作用为分发和处理消息的

构造函数,初始化handler looper 消息队列等
 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());
            }
        }

        mLooper = Looper.myLooper();//初始化looper
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;//赋值消息队列 looper会初始化消息队列 单链表结构
        mCallback = callback;//是否实现接口,handler里定义的一个回调接口
        mAsynchronous = async;//是否是异步消息
    }

发送消息

//返送一个runable  最终封装一个message 并作为message的一个属性
   public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
    //发送一个消息
     public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

最终进入MessageQueue进行入队

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;//包装需要处理的handler
        if (mAsynchronous) {
            msg.setAsynchronous(true);//一般发送的都是同步消息 ui绘制发送的为异步消息,同时会发送一个消息屏障 以优先处理异步消息
        }
        return queue.enqueueMessage(msg, uptimeMillis);//入队
    }

处理消息

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {// msg 是否设置runable
            handleCallback(msg);
        } else {
            if (mCallback != null) {// 是否实现handler里的接口
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);//最终走到重写的handleMessage方法
        }
    }

MessageQueue

入队保存消息
 boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {//handler为空
            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;//取消息head 
           //是否需要唤醒,looper一直循环next,会自动赋值mBlocked
            boolean needWake;
			//当前队列为空|消息时间为0|消息时间小于head时间
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;//插入队列头部 next指向 老的head
                mMessages = msg;//head 重置为当前message
                needWake = mBlocked;//根据阻塞判断是否需要唤醒
            } else {
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
				//当前消息时间大于head  插入队列
				//取出需要出入队列的前一个消息  初始值为head消息即mMessages
                Message prev;
			//例如 初始head 为when 1 next=3; next.next =6;当前msg when = 5
			//第一轮 prev = 1;p=3; 5<3 不成立 
			//第二轮 prev=3; p=6;5<6 break;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
					//说明时间大于head时间,已经处在队列中间  next取值时已经唤醒过
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
				//当前消息为5 next指向p=6
                msg.next = p; // invariant: p == prev.next 
				//需要插入的msg=3 next指向当前消息5
                // 最后为1,3,5,6
                prev.next = msg;
            }
             // 链表已经重新排完序 按照when 从小到大顺序
            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

从消息队列获取消息

Message next() {
        final long ptr = mPtr;
		//是否初始化完毕  构造消息队列时候会初始化,native实现的 一个标志 暂时不去研究底层的实现
        if (ptr == 0) {
            return null;
        }

        int pendingIdleHandlerCount = -1; // -1 only during first iteration
        int nextPollTimeoutMillis = 0;
        for (;;) {//无限循环
            if (nextPollTimeoutMillis != 0) {
                Binder.flushPendingCommands();
            }
//阻塞方法,主要是通过native层的epoll监听文件描述符的写入事件来实现的。
            nativePollOnce(ptr, nextPollTimeoutMillis);

            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());
                }
                if (msg != null) {
                    if (now < msg.when) {
					//计算时间 大于当前时间  设置阻塞时间,休眠 等待下一轮唤醒处理,
                    // 注意 并未取出消息进行处理
                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                    } else {
                        // Got a message.
						//小于当前时间  不需要阻塞  取出消息  重置链表结构
                        mBlocked = false;
						// premsg-->msg(异步或者普通消息)-->msg.next
						//中间获取到了消息,前一个msg 和msg.next 串起来
                        if (prevMsg != null) {
                            prevMsg.next = msg.next;
                        } else {
						//第一个就是 直接返回当前msg 重置head 为msg.next
                            mMessages = msg.next;
                        }
                        msg.next = null;//返回的msg next 置空
                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
                        msg.markInUse();
                        return msg;
                    }
                } else {
                    // No more messages.
                    nextPollTimeoutMillis = -1;//么有消息,无限阻塞,等待唤醒
                }

                // Process the quit message now that all pending messages have been handled.
                if (mQuitting) {
                    dispose();
                    return null;
                }
//就是 Handler 机制提供的一种,可以在 Looper 事件循环的过程中,当出现空闲的时候,允许我们执行任务的一种机制。定义时需要实现其 queueIdle() 方法,暂时先不研究
                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);
                    }
                }
            }
            pendingIdleHandlerCount = 0;
            nextPollTimeoutMillis = 0;
        }
    }

ViewRootImpl 中界面绘制时使用了消息屏障,优先处理界面绘制

void scheduleTraversals() {
    if (!mTraversalScheduled) {
        mTraversalScheduled = true;
        //插入一个消息屏障,屏蔽普通消息的处理
        mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
        mChoreographer.postCallback(
                Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
    }
}

void doTraversal() {
    if (mTraversalScheduled) {
        mTraversalScheduled = false;
        //移除消息屏障
        mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
    }
}

Looper

主线程parare时候会使用ThreadLocal存储当前的looper对象 主要用于线程隔离,保存数据的
 private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));//保存looper
    }
主线程开启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;

        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        final int thresholdOverride =
                SystemProperties.getInt("log.looper."
                        + Process.myUid() + "."
                        + Thread.currentThread().getName()
                        + ".slow", 0);

        boolean slowDeliveryDetected = false;

        for (;;) {//轮询消息
            Message msg = queue.next(); // 到消息队列获取消息
            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 traceTag = me.mTraceTag;
            long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
            long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
            if (thresholdOverride > 0) {
                slowDispatchThresholdMs = thresholdOverride;
                slowDeliveryThresholdMs = thresholdOverride;
            }
            final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
            final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);

            final boolean needStartTime = logSlowDelivery || logSlowDispatch;
            final boolean needEndTime = logSlowDispatch;

            if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }

            final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
            final long dispatchEnd;
            try {
                msg.target.dispatchMessage(msg);//回调对应handler方法
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
            ...........省略部分代码
    }

hander 回调方法

public void dispatchMessage(Message msg) {
        if (msg.callback != null) {// msg 是否设置runable
            handleCallback(msg);
        } else {
            if (mCallback != null) {// 是否实现handler里的接口
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);//最终走到重写的handleMessage方法
        }
    }

Message

消息实体类,获取消息和复用消息

    主要属性
   /*package*/ int flags;//标识

    /*package*/ long when;//时间

    /*package*/ Bundle data;//数据

    /*package*/ Handler target;//处理消息的handler

    /*package*/ Runnable callback;//可执行的runable

    // sometimes we store linked lists of these things
    /*package*/ Message next;//链表结构  持有下一个msg的引用

ThreadLocal

存储 以ThreadLocal为key  looper为value 存储
 public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);//ThreadLocalMap为ThreadLocal静态内部类 整体作为线程thread的一个属性存在
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
    // 获取对应线程的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();
    }

主要分发流程差不多就是这样了