View.post() can be used in the following two scenarios:

  • Asynchronous modifyUI.
  • Listening to theViewFinish drawing.

Realize the principle of

First look at the view.post () 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; }Copy the code

Here attachInfo! = null performs two kinds of logic.

When attachInfo == NULL, getRunQueue().post(action) is executed; .

private HandlerAction[] mActions; private int mCount; 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++; }}Copy the code

It stores Runnable in an array of initial size 4, and growingArrayUtils.append () is the logic for dynamic scaling.

Callbacks stored in the array are executed by the parameter Handler when the executeActions(Handler) method is called.

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; }}Copy the code

The executeActions(Handler) method is called in two places:

  • View.dispatchAttachedToWindow()
  • ViewRootImpl.performTraversals()

The dispatchAttachedToWindow() method is also called from the performTraversals() method.

private void performTraversals() { ... if (mFirst) { ... host.dispatchAttachedToWindow(mAttachInfo, 0); . }... getRunQueue().executeActions(mAttachInfo.mHandler); . }Copy the code

But only when the performTraversals() method is called for the first time. The rest of the calls raised by requestLayout() and invalidate() will execute the process below.

Since the Handler parameters in the executeActions(Handler) method are taken from mattachInfo.mhandler, which is a Handler for the main thread, there is no difference. Will be added to the main thread Handler for execution. The UI can be modified by calling view.post () in the child thread, essentially in the main thread.

Also, since the performTraversals() method is also executed by the main thread Handler and is called earlier than executeActions(Handler), view.post () can be used as a callback at the end of the UI drawing.

Then when attachInfo! = null, attachInfo.mHandler.post(action) is executed; . It is sent directly to the main thread Handler to wait for the next performTraversals() call.

That’s where view.post () comes in. Take a look at the viewrotimpl source code to help you understand.