美文网首页Android知识Android开发Android技术知识
Handler简单分析-runOnUiThread,view.p

Handler简单分析-runOnUiThread,view.p

作者: 姜康 | 来源:发表于2017-04-23 11:19 被阅读254次

    网上有很多关于Handler的帖子,但是看了那么多,不自己亲自分析一下,还是虚得很

    哪些地方用到了Handler?

    runOnUiThread(Runnable action)   
    
    

    我们在Activity中写处理逻辑的时候,经常会用到这个方法,用来保证代码在UI线程中执行。
    来看看它是怎么实现的:

     /**
         * Runs the specified action on the UI thread. If the current thread is the UI
         * thread, then the action is executed immediately. If the current thread is
         * not the UI thread, the action is posted to the event queue of the UI thread.
         *
         * @param action the action to run on the UI thread
         */
        public final void runOnUiThread(Runnable action) {
            if (Thread.currentThread() != mUiThread) {
                mHandler.post(action);
            } else {
                action.run();
            }
        }
    

    可以看到,如果当前线程是UI线程,则调用Handler的post方法。否则直接运行。
    那么就来看看Handler的post方法:

      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);
        }
    

    再往下:

    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);
        }
    

    可以看到最后调用的方法是 sendMessageAtTime(Message msg, long uptimeMillis),该方法将消息放入MessageQueque中。

    send系列

    其实上面这几个常用的方法最终也是调用的sendMessageAtTime(Message msg, long uptimeMillis)方法。

    View中的post方法
    它的作用是在UI线程中执行代码逻辑。

    废话不多说,看源码:

    /**
         * <p>Causes the Runnable to be added to the message queue.
         * The runnable will be run on the user interface thread.</p>
         *
         * @param action The Runnable that will be executed.
         *
         * @return Returns true if the Runnable was successfully placed in to the
         *         message queue.  Returns false on failure, usually because the
         *         looper processing the message queue is exiting.
         *
         * @see #postDelayed
         * @see #removeCallbacks
         */
        public boolean post(Runnable action) {
            final AttachInfo attachInfo = mAttachInfo;
            if (attachInfo != null) {
                return attachInfo.mHandler.post(action);
            }
    
            // Postpone the runnable until we know on which thread it needs to run.
            // Assume that the runnable will be successfully placed after attach.
            getRunQueue().post(action);
            return true;
        }
    

    View的显示都依赖于Window,而AttachInfo可以看作是View和Window的桥梁。
    这里可以看到如果attachInfo不为空,则会调用Handler的post方法,否则调用getRunQueue().post(action);
    这里来看一下getRunQueue().post(action)的实现

    /**
         * Returns the queue of runnable for this view.
         *
         * @return the queue of runnables for this view
         */
        private HandlerActionQueue getRunQueue() {
            if (mRunQueue == null) {
                mRunQueue = new HandlerActionQueue();
            }
            return mRunQueue;
        }
    

    好的,到HandlerActionQueue中看看去:

    public void post(Runnable action) {
            postDelayed(action, 0);
        }
    
        public void postDelayed(Runnable action, long delayMillis) {
            final HandlerAction handlerAction = new HandlerAction(action, delayMillis);
    
            synchronized (this) {
                if (mActions == null) {
                    mActions = new HandlerAction[4];
                }
                mActions = GrowingArrayUtils.append(mActions, mCount, handlerAction);
                mCount++;
            }
        }
    
    public void executeActions(Handler handler) {
            synchronized (this) {
                final HandlerAction[] actions = mActions;
                for (int i = 0, count = mCount; i < count; i++) {
                    final HandlerAction handlerAction = actions[i];
                    handler.postDelayed(handlerAction.action, handlerAction.delay);
                }
    
                mActions = null;
                mCount = 0;
            }
        }
    

    可以看到实际上是把线程放入了 HandlerAction数组中,然后在view中会调用
    executeActions方法传入handler,然后调用它的postDelayed方法。

    相关文章

      网友评论

        本文标题:Handler简单分析-runOnUiThread,view.p

        本文链接:https://www.haomeiwen.com/subject/cunezttx.html