Screen display mechanism
- The CPU computes the data (the View tree traverses and performs the three processes: measurement, layout, and drawing) and then hands the data over to the GPU
- GPU render processing, and then put the data into the Buffer.
- The display takes data from the buffer and displays it.
What causes frame loss in general?
The main thread has time-consuming operation, which delays drawing the View.
Reference:
A brief analysis of Android Vsync principles
Android refresh rate 60 frames/second, every 16ms onDraw?
The display is refreshed every 16ms, but onDraw is called only when the user makes a redraw request.
Does the screen refresh immediately after onDraw?
No, it waits for the next Vsync signal.
Will the screen refresh every 16ms if the interface is not redrawn?
For the underlying display, the data in the buffer is displayed once every 16.6ms when the VSYNC signal is received. So it will definitely refresh. (Using old data)
Will I lose frames if I draw onDraw when the screen is about to refresh
The View redraw initiated by the code will not be executed immediately. It will wait until the next VSYNC signal arrives. It doesn’t matter when you draw it.
If you call requestLayout 10 times quickly, will you call onDraw 10 times?
The mTraversalScheduled variable is used to filter repeated refresh requests within a frame. The initial value is false and will be reset to false when the frame is drawn (doTraversal(), which will be analyzed later). At the same time, This is also set to false in unscheduleTraversals(). This means that scheduleTraversals() is normally invoked only once before the frame is drawn. The reason for this is that the ViewRootImpl binds to the DecorView, and the entire DecorView is handled once when it is refreshed, so the scheduleTraversals() function is the same for different views. So one refresh request in the same frame is the same as multiple refresh requests.
void scheduleTraversals() { if (! mTraversalScheduled) { mTraversalScheduled = true; MTraversalBarrier = mhandle.getLooper ().getQueue().postSyncbarrier (); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); . } } void doTraversal() { if (mTraversalScheduled) { mTraversalScheduled = false; // Remove the synchronization barrier mhandler.getLooper ().getQueue().removesyncbarrier (mTraversalBarrier); . performTraversals(); . }}Copy the code
UI rendering process
-
Any View refresh request on the interface eventually goes through scheduleTraversals() in the ViewRootImpl to arrange a traversal of the View tree.
-
ScheduleTraversals () filters out repeated calls within the same frame, ensuring that only one traversal is required within the same frame, and all views that need to be refreshed are redrawn during the traversal.
-
ScheduleTraversals () sends a synchronization barrier to the main thread’s message queue, intercepting all synchronous messages after this time, but not asynchronous messages, so that the View tree can be traversed as quickly as possible when a screen refresh signal is received.
-
After issuing the synchronization barrier, scheduleTraversals() wraps performTraversals() into Runnable and calls Choreographer postCallback().
-
The postCallback() method first puts the Runnable task in a queue with the current timestamp, then calls a native layer method directly if it is in the main thread, or sends a highest-priority message to the main thread if it is not. Let the main thread call this native layer method first.
-
This method on the Native layer is used to subscribe the next screen refresh signal Vsync to the underlying layer. When the next screen refresh signal is emitted, the underlying layer will call back to Choreographer’s onVsync() method to notify the upper layer app.
-
When the onVsync() method is called back, an asynchronous message executing the doFrame() method is sent to the message queue on the main thread.
-
The doFrame() method executes by fetching the task that was previously placed in the queue. The fetched task is actually the doTraversal() operation of the ViewRootImpl.
-
DoTraversal () first removes the synchronization barrier, PerformMeasure (), perfromLayout(), performDraw(), performMeasure(), perfromLayout(), performDraw(), performMeasure() In each of these processes, the View tree is traversed to refresh the View that needs to be updated.
-
Wait until the next Vsync signal arrives to render the data calculated above to the screen and start processing the next frame if necessary.
Reference:
- Android UI refresh mechanism
- Android screen refresh mechanism
- A brief analysis of Android Vsync principles
- android triple buffer
- Android interview Questions – Refresh mechanism (9 questions)