View. post () is not reliable, you know how much, view. post is reliable
I. Preface
Sometimes, we needView.post()
To send a Runnable to the main thread for execution. All of this looks beautiful, and it will eventually passHandler.post()
Method to execute, and avoid redefining a Handler object.
However, from Android 7.0 (Api level 24), View. post () will no longer be so reliable. The Runnable you post () may never have the chance to execute it.
Ii. post differences in 7.0
2.1 differences between post Methods
As mentioned above, this problem only occurs on Android 7.0. First, we will analyze the changes made to View. post () in Android 7.0 from the source code.
Use Diff to check their differences. On the left side is the Api Level 24 + (Api24) code, and on the right side is the Api level 23-(Api23) code.
Obviously, we can see that they are onlymAttachInfo
When it is null, the execution logic is different.
In Api24getRunQueue().post(action)
And Api23 will call ViewRootImpl.getRunQueue().post(action)
Method, and their difference is here.
2.2 details of Api23 post
Let's take a simple look,ViewRootImpl
What is it.
ViewRootImpl
It can be understood as an instance of the root node of the ViewTree of an Activity. Each ViewRootImpl is used to manage DecorView and ViewTree.
ViewRootImpl
The queue used to carry Runnable is sRunQueues, which is a static variable, that is, during the life cycle of the App,ViewRootImpl
The message queue in is the same.
Let's take a look at the aforementionedViewRootImpl.getRunQueue().post()
What did you do?
post()
The method simply wraps it into a HandlerAction object and puts it in the ArrayList of mActions. To continue tracing, you need to know when the HandlerAction added to mActions is consumed.
Where HandlerAction is consumed, yesexecuteActions()
Method.
In the end, it is still called.handler.postDelayed()
There is nothing to say. The key point is executeAction()
Method, when is it called.
executeAction()
Is called by TraversalRunnabledoTraversa()
, IndoTraversa()
Method. And TraversalRunnable isChoreographer.postCallBack()
Called cyclically. This Choreographer
PassdoScheduleCallback()
Send oneMSG_DO_SCHEDULE_CALLBACK
A type of message is called cyclically. The interval is a VSync interval.
Choreographer is not the focus of this Article. If you are interested, you can take a look at it separately.
Therefore, under Api23,executeAction()
It will be called cyclically. Basically, the mActions in it will be consumed immediately as long as there is an unexecuted Runnable.
Therefore, on devices below Api23, View. post () is basically reliable, and Runnable after the post operation will have the opportunity to execute it.
2.3 Api24 details
Let's take a look at the implementation details in Api24. what is called in Api24? getRunQueue().post()
Method, which operates onHandlerActionQueue
Object.
The internal structure is actually very similar to Api23. It also maintains an array of HandlerAction mActions.
Where mActions is finally consumed, it is stillexecuteActions()
Method.
Back to the fundamental question,executeActions()
When the method will be called, continue tracing and you can see it inView.dispatchAttachedToWindow()
Method.
Since, executeActions()
Method, in Api24 or later, onlydispatchAttachedToWindow()
To be called.View.dispatchAttachedToWindow()
Method, only through this ViewaddView()
When a ViewGroup is added, it is called. This leads to the control written in the Layout and won't have the opportunity to call it again.addView()
Method, so it will never be executed. This is when Api24,View.post()
The performance is inconsistent.
Iii. Summary
View.post()
The root cause of the differences between different versions is in Api23 and Api24,executeActions()
The call time of the method is different. As a result, the View performs differently when there is no mAttachInfo object.
Therefore, we need to use it with caution in the Process of use to distinguish the actual use scenario. Generally, You can standardize your own code:
After the View is displayed, callView.post()
Method (mAttachInfo is not empty at this time ).
Avoid usingView.post()
Method, which can be used directlyHandler.post()
Method.
Summary
The above is a small Editor to introduce to you the View. post () is not reliable, I hope to help you, if you have any questions, please leave a message, the small editor will reply to you in a timely manner. Thank you very much for your support for the help House website!