In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article shows you how the three major processes of Android View drawing are, concise and easy to understand, which can definitely brighten your eyes. I hope you can get something through the detailed introduction of this article.
Introduction
The workflow of View mainly refers to the three major processes of measure, layout and draw, that is, measurement, layout and drawing, in which measure determines the measurement width and height of View, layout determines the location of the four vertices of View in its parent View according to the measured width and height, and draw draws View to the screen, so that through the recursive traversal of ViewGroup, a View tree is displayed on the screen. To put it simply, let's take you to analyze the source code step by step:
The View of Android is tree-structured:
Basic concept
Before introducing the three major processes of View, we must introduce some basic concepts in order to better understand the whole process.
The concept of Window
Window represents the concept of a window, it is an abstract concept from the perspective of WindowManagerService. All views in Android are presented through Window, whether it is Activity, Dialog or Toast, as long as there is View, there must be Window.
It is important to note that this abstract concept of Window is not the same thing as the class PhoneWindow. PhoneWindow represents the abstraction of the mobile screen. It acts as an intermediary between Activity and DecorView, and View can be displayed even without PhoneWindow.
Apart from everything, only from the point of view of WindowManagerService, the interface of Android is cascading by Window, while Window is an abstract concept, it does not actually exist, it exists in the form of View, this View is DecorView.
With regard to Window, let's first get a general idea.
The concept of DecorView
DecorView is the top level of the entire Window interface. View,View measurements, layout, drawing, and event distribution are all traversed by DecorView down the View tree. DecorView, as a * View, usually contains a vertical LinearLayout. There are two parts in this LinearLayout (depending on the version and topic of the Android), with [title bar] above and [content bar] below. In Activity, the layout file we set through setContentView is actually loaded into the content bar, and the id of the content bar is content, so the method of specifying the layout is called setContent ().
The concept of ViewRoot
ViewRoot corresponds to the ViewRootImpl class, which is the link between WindowManager and DecorView. The three major processes of View are all completed through ViewRoot. In ActivityThread, when the Activity object is created, the DecorView is added to the Window, and the corresponding ViewRootImpl is created, and the ViewRootImpl and DecorView are associated and saved to the WindowManagerGlobal object.
WindowManagerGlobal.java root = new ViewRootImpl (view.getContext (), display); root.setView (view, wparams, panelParentView)
Java
The drawing process of View starts with ViewRoot's performTraversals method, which goes through three processes of measure, layout and draw to finally draw a View, as shown in the following figure:
Measure measurement
In order to better understand the measurement process of View, we also need to understand MeasureSpec, which is an inner class of View and represents the measurement specification of View. MeasureSpec represents a 32-bit int value, the high 2 bits represent SpecMode (measurement mode), and the lower 30 bits represent SpecSize (measurement size). We can take a look at its implementation:
MeasureSpec.java public static class MeasureSpec {private static final int MODE_SHIFT = 30; private static final int MODE_MASK = 0x3 = 0) {/ / Child wants a specific size... So be it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY;} else if (childDimension = = LayoutParams.MATCH_PARENT) {/ / Child wants to be our size, but our size is not fixed. / / Constrain child to not be bigger than us. ResultSize = size; resultMode = MeasureSpec.AT_MOST;} else if (childDimension = = LayoutParams.WRAP_CONTENT) {/ / Child wants to determine its own size. It can't be / / bigger than us. ResultSize = size; resultMode = MeasureSpec.AT_MOST;} break; / / Parent asked to see how big we want to be case MeasureSpec.UNSPECIFIED: if (childDimension > = 0) {/ / Child wants a specific size... Let him have it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY;} else if (childDimension = = LayoutParams.MATCH_PARENT) {/ / Child wants to be our size... Find out how big it should / / be resultSize = View.sUseZeroUnspecifiedMeasureSpec? 0: size; resultMode = MeasureSpec.UNSPECIFIED;} else if (childDimension = = LayoutParams.WRAP_CONTENT) {/ / Child wants to determine its own size.... Find out how / / big it should be resultSize = View.sUseZeroUnspecifiedMeasureSpec? 0: size; resultMode = MeasureSpec.UNSPECIFIED;} break;} / / noinspection ResourceType return MeasureSpec.makeMeasureSpec (resultSize, resultMode);}
Java
The above code creates the MeasureSpec of child elements based on the MeasureSpec of the parent class and its own LayoutParams. The specific process is analyzed by students. The final creation rules are shown in the following table:
After traversing the sub-View, ViewGroup needs to determine its final measurement size according to the measurement results of the sub-elements, and calls the setMeasuredDimension method to save the measurement width and height.
SetMeasuredDimension (resolveSizeAndState (maxWidth, widthMeasureSpec, childState), heightSizeAndState)
Java
Here, resolveSizeAndState is called to determine the final size, mainly to ensure that the measured size cannot exceed the * remaining space maxWidth of the parent container. Here, let's take a look at its implementation:
Public static int resolveSizeAndState (int size, int measureSpec, int childMeasuredState) {final int specMode = MeasureSpec.getMode (measureSpec); final int specSize = MeasureSpec.getSize (measureSpec); final int result; switch (specMode) {case MeasureSpec.AT_MOST: if (specSize < size) {result = specSize | MEASURED_STATE_TOO_SMALL } else {result = size;} break; case MeasureSpec.EXACTLY: result = specSize; break; case MeasureSpec.UNSPECIFIED: default: result = size } return result | (childMeasuredState & MEASURED_STATE_MASK);}
Java
The onMeasure process of a specific ViewGroup is not analyzed here. Because the measurement methods of each layout are different, it is impossible to analyze them one by one, but the steps in their onMeasure are regular:
1. Traverse the Children elements according to their respective measurement rules, and call the getChildMeasureSpec method to get the measureSpec of the Child
two。 Call the measure method of Child
3. Call setMeasuredDimension to determine the final size.
Measure of View
The measure process of View is completed by its measure method, and the measure method is a method of type final, which means that the subclass cannot override this method. The onMeasure method will be called in the measure method of View. We only need to look at the implementation of onMeasure here, as follows:
View.java protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension (getDefaultSize (getSuggestedMinimumWidth (), widthMeasureSpec), getDefaultSize (getSuggestedMinimumHeight (), heightMeasureSpec);}
Java
The code is simple, so let's move on to the implementation of the getDefaultSize method:
View.java public static int getDefaultSize (int size, int measureSpec) {int result = size; int specMode = MeasureSpec.getMode (measureSpec); int specSize = MeasureSpec.getSize (measureSpec); switch (specMode) {case MeasureSpec.UNSPECIFIED: result = size; break; case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = specSize; break } return result;}
Java
As can be seen from the above code, the width / height of View is determined by specSize, and custom controls that directly inherit View need to override the onMeasure method and set the size of the wrap_content itself, otherwise using wrap_content in the layout is equivalent to using match_parent.
The above is the approximate measure process of View. After the completion of the measure, the measured width and height can be obtained by the getMeasuredWidth/Height method, which is generally equal to the final width and height of the View, because the layout layout of View is set according to the measureWidth/Height, unless the feature value is modified in the layout.
Layout layout
The role of Layout is that ViewGroup is used to determine the location of child elements. When the location of ViewGroup is determined, it iterates through all child elements in onLayout and calls its layout method. To put it simply, the layout method determines the location of the View itself, while the onLayout method determines the location of all child elements.
First, take a look at the layout method of View:
Public void layout (int l, int t, int r, int b) {if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT)! = 0) {onMeasure (mOldWidthMeasureSpec, mOldHeightMeasureSpec); mPrivateFlags3 & = ~ PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;} int oldL = mLeft; int oldT = mTop; int oldB = mBottom; int oldR = mRight Boolean changed = isLayoutModeOptical (mParent)? SetOpticalFrame (l, t, r, b): setFrame (l, t, r, b); if (changed | | (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) = = PFLAG_LAYOUT_REQUIRED) {onLayout (changed, l, t, r, b); if (shouldDrawRoundScrollbar ()) {if (mRoundScrollbarRenderer = = null) {mRoundScrollbarRenderer = new RoundScrollbarRenderer (this) }} else {mRoundScrollbarRenderer = null;} mPrivateFlags & = ~ PFLAG_LAYOUT_REQUIRED; ListenerInfo li = mListenerInfo; if (li! = null & & li.mOnLayoutChangeListeners! = null) {ArrayList listenersCopy = (ArrayList) li.mOnLayoutChangeListeners.clone () Int numListeners = listenersCopy.size (); for (int I = 0; I < numListeners; + + I) {listenersCopy.get (I) .onLayoutChange (this, l, t, r, b, oldL, oldT, oldR, oldB);} mPrivateFlags & = ~ PFLAG_FORCE_LAYOUT; mPrivateFlags3 | = PFLAG3_IS_LAID_OUT }
Due to the word limit of Wechat, please click on the original link to view the full content
At this point, we are done with the three major processes of View: measure, layout and draw. Here is a summary:
If it is a custom ViewGroup, you need to rewrite the onMeasure method to traverse the quantum elements in the onMeasure method, just like the onLayout method. * implement the onDraw method to draw yourself.
If you customize View, you need to write the onMeasure method to deal with the case of wrap_content. You do not need to deal with onLayout,*** to implement the onDraw method to draw yourself.
The above is what the three major processes of Android View drawing are like. Have you learned the knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.