Parse the view. post method. Analyze the flow of this method.
The post method is a Runnable object that receives a Runnable object. So what’s the difference between these two approaches?
The POST method of the Handler
First, take a quick look at the Handler’s POST (Runnable) method. This method adds a Runnable to the message queue and is executed in the thread associated with the handler.
Below is the associated partial source code. You can see that the incoming Runnable object, loaded with Message, is added to the queue.
Handler related part of the source code
// Android. OS Handler for the source code
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);
}
Copy the code
For details about the process, see Handler
View post method
Let’s just follow post’s source code.
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(a) {
if (mRunQueue == null) {
mRunQueue = new HandlerActionQueue();
}
return mRunQueue;
}
Copy the code
As you can see, the initial query is for attachInfo, and if so, the attachInfo.mHandler is used to perform this task.
If there is no attachInfo, add it to the View’s own mRunQueue. Determine the thread to run before executing the task.
Post (Runnable Action) returns a Boolean value, if true, indicating that the task has been added to the message queue. False usually indicates that the looper associated with the message queue is exiting.
So we need to know about AttachInfo and HandlerActionQueue.
AttachInfo
AttachInfo is the static inner class of the View. Once the View is associated with the parent window, it uses this class to store some information.
AttachInfo Stores some of the following information:
WindowId mWindowId
A sign of the windowView mRootView
The view at the topHandler mHandler
This handler can be used to process tasks
HandlerActionQueue
When the View doesn’t have a handler, use the HandlerActionQueue to cache tasks. HandlerAction is its static inner class that 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;
// ...}}Copy the code
The View of mRunQueue
Runnable tasks into a queue. These tasks are performed when the View is associated with a window and there is a handler.
/** * Queue of pending runnables. Used to postpone calls to post() until this * view is attached and has a handler. */
private HandlerActionQueue mRunQueue;
Copy the code
When will the task stored in the mRunQueue be executed? Let’s focus on the dispatchAttachedToWindow method.
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
// ...
// Transfer all pending runnables.
if(mRunQueue ! =null) {
mRunQueue.executeActions(info.mHandler);
mRunQueue = null;
}
// ...
}
Copy the code
This method calls mrunqueue.executeActions.
The executeActions(Handler Handler) method actually uses the Handler passed in to process the tasks in the queue.
And this dispatchAttachedToWindow is going to be called in the ViewGroup.
Or call it in view rule PL
host.dispatchAttachedToWindow(mAttachInfo, 0);
Copy the code
summary
The View post method actually uses the AttachInfo handler.
If the View does not currently have AttachInfo, the task is added to the View’s own HandlerActionQueue queue and then handed to the incoming AttachInfo handler in dispatchAttachedToWindow. You can also think of view.post as using handler.post.
When we get the width and height of the View, we will use the View post method, which is to wait until the View is actually associated with the window to get the width and height information.
The flow chart is summarized as follows