Android View Post method

Resolve the view.post method. Analyze the flow of this method.

Speaking of the post method, we can easily think of the post method of the handler, which receives a runnable object. So what's the difference between the two methods?

Let's take a brief look at the post (runnable) method of handler. This method adds a runnable to the message queue and will be executed in the thread associated with the handler.

The following is part of the associated source code. You can see that the incoming runnable object is added to the queue after loading the message.

Handler related part of the source code

    // android.os Handler 有关的部分源码
    public final boolean post(@NonNull Runnable r) {
        return sendMessageDelayed(getPostMessage(r),0);
    }

    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

    public final boolean sendMessageDelayed(@NonNull Message msg,long delayMillis) {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg,SystemClock.uptimeMillis() + delayMillis);
    }

    public boolean sendMessageAtTime(@NonNull 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(@NonNull MessageQueue queue,@NonNull Message msg,long uptimeMillis) {
        msg.target = this;
        msg.workSourceUid = ThreadLocalWorkSource.getUid();

        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg,uptimeMillis);
    }

See the introduction of handler for the specific process

We directly follow the source code of post.

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

private HandlerActionQueue getRunQueue() {
    if (mRunQueue == null) {
        mRunQueue = new HandlerActionQueue();
    }
    return mRunQueue;
}

You can see whether there is attachinfo at the beginning. If so, use attachinfo.mhandler to perform this task.

If there is no attachinfo, it is added to the view's own mrunqueue. Determine the running thread before executing the task.

The Boolean value returned by post (runnable action). If true, it indicates that the task has been added to the message queue. If false, it usually indicates that the looper associated with the message queue is exiting.

Then we need to know attachinfo and handleractionqueue.

Attachinfo is a static inner class of view. After the view is associated with the parent window, this class is used to store some information.

Attachinfo stores some information as follows:

When the view does not have a handler, take the handleractionqueue to cache the task. Handleraction is its static internal class, which stores runnable and delay information.

public class HandlerActionQueue {
    private HandlerAction[] mActions;
    
    public void post(Runnable action)
    public void executeActions(Handler handler)
    // ...

    private static class HandlerAction {
        final Runnable action;
        final long delay;
        // ...
    }
}

Queue tasks (runnable). Perform these tasks after the view is associated with the upper window and has a handler.

/**
 * Queue of pending runnables. Used to postpone calls to post() until this
 * view is attached and has a handler.
 */
private HandlerActionQueue mRunQueue;

When will the tasks stored in this mrunqueue be executed? We focus on the dispatchattachedtowindow method.

void dispatchAttachedToWindow(AttachInfo info,int visibility) {
    // ...
    // Transfer all pending runnables.
    if (mRunQueue != null) {
        mRunQueue.executeActions(info.mHandler);
        mRunQueue = null;
    }
    // ...
}

Mrunqueue.executeactions is called in this method.

The executeactions (handler handler) method actually uses the incoming handler to process the tasks in the queue.

The dispatchattachedtowindow will be called in the ViewGroup.

Or call in ViewRootImpl.

host.dispatchAttachedToWindow(mAttachInfo,0);

The post method of view actually uses the handler of attachinfo.

If the view does not have attachinfo at present, the task is added to the view's own handleractionqueue queue, and then the task is handed over to the handler of the incoming attachinfo in dispatchattachedtowindow. You can also think that view.post uses handler.post.

When obtaining the width and height of the view, we will use the post method of the view, that is, we will get the width and height information after the view is really associated with the window.

The flow chart is summarized as follows

See recent updates to the Android collection for more information

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>