Android Handler消息机制原码解读

android的消息机制包括:handler(处理者)、looper(循环)、messageQueue(消息队列)、message消息。

这里先理解一个消息队列这个概念,handler的消息队列是先进先出的链表结构,下面是模拟消息队列写的一些方法。

消息类的写法

public class MessageData {
    //传递的数据类型,以作判断
    public int status;
    //你需要处理的数据
    public Object data;
    //用于连接消息的类
    public MessageData message;
    //最多连接数,这里没做处理
    public int linkedSize = 0;

}

消息队列的写法

public class MessageQueueData {
    private MessageData messageData;

   //入队:将消息存入消息队列中
    public void enqueueMessage(MessageData messageData) {
        Log.e("MessageQueueData", "enqueueMessage:" + messageData.status);
        //判断消息队列是否为空,如果为空,就讲链条的第一个消息置位假如的消息
        if (this.messageData == null) {
            this.messageData = messageData;
            this.messageData.message = null;
        } else {
            //如果不为空,进行链条循环,
            //将链条的第一数据赋值
            MessageData tempMy = this.messageData;
            MessageData tempInner;
            for (; ; ) {
                //取出该数据中用于连接的数据
                tempInner = tempMy.message;
                //如果该数据不为空,将该数据置为链条的类
                if (tempInner != null) {
                    tempMy = tempInner;
                } else {
                    //如果该数据为空,将该数据假如链条,结束循环
                    tempMy.message = messageData;
                    break;
                }

            }

        }

    }
    //出队,将消息从消息队列中取出
    public void next() {
        if (this.messageData != null) {
            Log.e("MessageQueueData", "next:" + this.messageData.status);
            //取出消息,将内部连接到该类中
            this.messageData = this.messageData.message;
        }
    }

}

执行过后的数据为

这里就体现出了先进先出的逻辑,好了,下面自定义一个looper循环的定时器

 private class HandlerThread extends Thread {

        private Handler mHandler;
        private TimmerRunnable mTimmerRunnable;
        private int time = 0;

        public HandlerThread() {
            mTimmerRunnable = new TimmerRunnable();
        }

        @Override
        public void run() {
            super.run();
            //创建该线程的looper,一个线程只能创建一个looper
            Looper.prepare();
            //创建该线程的handler
            mHandler = new Handler();
            //发送消息,及消息入队
            mHandler.post(mTimmerRunnable);
            //开始循环,进入循环获取消息
            Looper.loop();
        }

        public void stopThread() {
            //退出循环,结束线程
            mHandler.getLooper().quit();
        }

        private class TimmerRunnable implements Runnable {

            @Override
            public void run() {
                //消息会送,在这里处理你的消息,这样就实现了一个消息循环了,完成定时器
                time++;
                tv_time.post(new Runnable() {
                    @Override
                    public void run() {
                        tv_time.setText("时间:" + time);
                    }
                });
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                mHandler.post(mTimmerRunnable);
            }
        }

    }

先从创建开始,这里调用looper的prepare()

//先调用的这个方法
 public static void prepare() {
        prepare(true);
    }

//做空判断,如果该线程已近存在looper了就会抛出异常,所以一个线程只能有一个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中
private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

Handler的创建

//没有传入参数的构造方法
 public Handler() {
        this(null, false);
    }
//调用的是该构造函数
 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,如果该线程的looper不存在,就会抛出异常
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        //将looper创建的MessageQueue赋值到handler中
        mQueue = mLooper.mQueue;
        //消息处理接口,用于从消息队列出去后发送回主界面,以便于实现你的代码
        mCallback = callback;
        mAsynchronous = async;
    }

接下来进入Looper的循环机制

//进入循环
public static void loop() {
        //获取该线程的looper,如果为空则抛出异常
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        //获取looper中创建的消息队列
        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;
        //进入死循环,循环读取消息队列中的消息
        for (;;) {
            //获取消息队列的消息,如果消息队列返还为空,则跳出循环结束该方法
            //消息队列中,当队列中的消息问空的时候会进入死循环,这里会进入阻塞状态
            //只用手动调用queue.quit()方法才会返回空,然后结束该方法,结束线程
            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 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 {
                //经过一些列的数据处理,当到达这里的时候,将Message小心中的handler取出来
                //然后调用handler的dispatchMessage方法,将消息进行分发
                msg.target.dispatchMessage(msg);
                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }
           …………
            //释放Message,将Message数据重置,然后开始下一次消息的读取
            msg.recycleUnchecked();
        }
    }

消息队列的数据读取,出队,MessageQueue.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();
            }

            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;
                //判断该消息和该消息保存的handler是
                //如果该消息不为空,但是该消息的handler为空,进入
                if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        //赋值,将该消息赋值给prevMsg,同时取出该消息内部存储的消息,
                        //赋值到msg中
                        prevMsg = msg;
                        msg = msg.next;
                        //满足条件,则继读取下一个链条的数据
                    } while (msg != null && !msg.isAsynchronous());
                }
                //如果不为空
                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;
                }

                 //手动调用quit方法,结束该方法,返还空,到looper.loop层,然后结束该线程
                // Process the quit message now that all pending messages have been handled.
                if (mQuitting) {
                    dispose();
                    return null;
                }
……………………
        }
    }

接下来是消息分发了,handler.dispatchMessage方法

/**
     * Handle system messages here.
     */
//这里是判断调用的是handler的post方法还是sendMessage方法
    public void dispatchMessage(Message msg) {
        //取出保存在message的handler的callback方法,如果该保存了该方法,就调用回调的
        //post方法中的
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
        //如果调用的是sendMessage方法,就会调用handleMessage,需要在创建Handler中重新改方法
        //收取数据
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

这样就完成了出队的所有流程了。

接下来是入队,入队分为handler.post和handler.sendMessage两种方法入队

先讨论handler.post方法

  public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }
//创建Message
private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }
//进入到这个方法中
  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);
    }
//在这个方法中开始进入MessageQueue的入队方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

下面是MessageQueue中的enqueueMessage方法

boolean enqueueMessage(Message msg, long when) {
        //当message中没有保存handler的时候抛出异常
        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;
            //当链表中第一个位置的数据不存在的时候,将保持的数据加入到链条首位
            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;
    }

至此,hander的入队出队就完成了

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章