Android_View_View rendering process, android_view_view

Source: Internet
Author: User

Android_View_View rendering process, android_view_view
1. Drawing Process of the View tree

When the Activity receives the focus, it will be requested to draw the layout. This request is processed by the Android framework. The painting starts from the root node, and the layout tree is measured and draw. The drawing process of the entire View tree is shown inViewRoot.javaClassperformTraversals()Function expansion. The work done by this function can be simply described as whether to recalculate the View Size (measure) and whether to relocate the view location (layout) and whether to re-draw (draw). The flowchart is as follows:

View process function call chain

Pictures from https://plus.google.com/+ArpitMathur/posts/cT1EuBbxEgN
It must be noted that the user takes the initiative to call the request and only starts the measure and layout processes, rather than the draw process.

2. Concepts

Measure and layout

Overall, the steps of Measure and Layout are as follows:
Tree traversal is ordered, from the parent View to the Child View. Each ViewGroup is responsible for ing all its child views, and the bottom View is responsible for ing itself.

Detailed analysis
The measure process consistsmeasure(int, int)Method initiation, ordered measurement View from top to bottom. At the end of the measure process, each View stores its own Size and measurement specifications. The layout process is composedlayout(int, int, int, int)Method initiation is also top-down traversal. In this process, each parent view is placed in its own child view based on the size obtained by the measure process.

The measure process assigns values to the mMeasuredWidth and mMeasuredHeight variables of a View and all sub-nodes.getMeasuredWidth()AndgetMeasuredHeight()Method. These two values must be within the constraints of the parent view to ensure that all parent views receive measurements from all child views. If the child view is not satisfied with the size of the measurement, the parent view will intervene and set the measurement rule for the second measurement. For example, the parent view can measure each subview Based on the unspecified dimension. If the size of the subview is too large or too small, the parent view uses an exact size to measure the child view again.

Two classes of transfer dimensions during the measure Process

  • ViewGroup. LayoutParams (View layout parameters)
  • MeasureSpecs class (parent view's measurement requirements for child views)

ViewGroup. LayoutParams
This class is common and is used to specify parameters such as the height and width of the view. For the height and width of each view, you have the following options:

  • Value
  • MATCH_PARENT indicates that the child view is as big as the parent view (excluding the padding value)
  • WRAP_CONTENT indicates that the view is good enough to wrap its content size (including the padding value)

The subclass of ViewGroup has its corresponding subclass of ViewGroup. LayoutParams. For example, RelativeLayoutParams, a subclass of ViewGroup. LayoutParams owned by RelativeLayout, is used.
Sometimes we need to use the view. getLayoutParams () method to obtain a view LayoutParams and perform forced conversion. However, if we do not know its specific type, it may cause a forced conversion error. In fact, this method obtains the LayoutParams of the parent View type. For example, if the parent control of the View is RelativeLayout, The LayoutParams type is RelativeLayoutParams.

MeasureSpecs
Measurement specifications, including measurement requirements and dimensions. Three modes are available:

  • UNSPECIFIED
    The parent view does not have any constraints on the Child view. It can reach any expected size. For example, ListView and ScrollView are not commonly used in custom views,

  • EXACTLY
    The parent view specifies an exact size for the Child view. No matter how large the child view is, it must be within the boundary of the specified size. The corresponding attribute is match_parent or specific, such as 100dp, the parent control can useMeasureSpec.getSize(measureSpec)Obtain the size of the Child widget.

  • AT_MOST
    The parent view specifies a maximum size for the Child view. In this mode, the parent control cannot determine the size of the Child View, the child control can only calculate its own size as needed. This mode is the case where we need to implement the measurement logic for custom views.

3. Core measure Method
  • Measure (int widthMeasureSpec, int heightMeasureSpec)
    This method is defined inView.javaClass, which is of the final type and cannot be rewritten. However, the measure call chain calls backonMeasure()Method. Therefore, you only need to re-write the custom view.onMeasure()Method.

  • OnMeasure (int widthMeasureSpec, int heightMeasureSpec)
    This method is used to implement the measurement logic in a custom view. The parameters of this method are the measurement requirements of the parent view on the width and height of the Child view. In our own custom view, we need to calculate the width and height of the view based on the widthMeasureSpec and heightMeasureSpec. Different modes have different processing methods.

  • SetMeasuredDimension ()
    The ultimate method in the measurement phase, inonMeasure(int widthMeasureSpec, int heightMeasureSpec)To pass the calculated size to the method. The measurement phase ends. This method must also be called. Otherwise, an exception is reported. When you customize a view, you do not need to care about the complicated Measure process of the system. You only need to callsetMeasuredDimension()Set the size calculated based on MeasureSpec. For details, refer to the onMeasure method of ViewPagerIndicator.

Next let's take the ViewGroup'smeasureChildren(int widthMeasureSpec, int heightMeasureSpec)The method analyzes the Measure process of the composite View: the method call flowchart of MeasureChild:

Source code analysis

/*** Request all the sub-views to measure themselves. Some of the items to be considered include the ing requirements of the sub-views MeasureSpec and their own padding. * all the sub-views in the GONE state are skipped here, the most important task is the ** @ param widthMeasureSpec requirements for width ing of the View in the getChildMeasureSpec Method * @ param heightMeasureSpec: The height ing requirements for the View */protected void measureChildren (int widthMeasureSpec, int heightMeasureSpec) {final int size = mChildrenCount; final View [] children = mChildren; for (int I = 0; I <size; ++ I) {final View child = children [I]; if (child. mViewFlags & VISIBILITY_MASK )! = GONE) {measureChild (child, widthMeasureSpec, heightMeasureSpec) ;}} protected void measureChild (View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {final LayoutParams lp =. getLayoutParams (); // get Child's LayoutParams final int childWidthMeasureSpec = getChildMeasureSpec (parentWidthMeasureSpec, // get ChildView's widthMeasureSpec mPaddingLeft + mPaddingRight, lp. width); final Int childHeightMeasureSpec = getChildMeasureSpec (parentHeightMeasureSpec, // obtain the heightMeasureSpec mPaddingTop + mPaddingBottom, lp. height); child. measure (childWidthMeasureSpec, childHeightMeasureSpec);}/*** this method is the heaviest part of measureChildren and calculates its own MeasureSpec for each ChildView. * The goal is to combine the MeasureSpec and LayoutParams of ChildView to get the most appropriate result. ** @ Param spec ing requirements for this View * @ param padding: the current View is on the paddingand, it may also contain margins ** @ param childDimension specific to the current dimension (height or width) * @ return sub-view MeasureSpec */public static int getChildMeasureSpec (int spec, int padding, int childDimension ){......... // create the MeasureSpec return MeasureSpec of the subview Based on the measurement requirements and size of the obtained subview. makeMeasureSpec (resultSize, resultMode);}/*** used to obtain the final size of the View. The parent View provides a wide and high constraint letter. * The real measurement of a View is called in onMeasure (int, int. * Therefore, only onMeasure (int, int) can be used and must be overwritten. ** @ param widthMeasureSpec is in the horizontal direction, the Measure specified by the parent view * @ param heightMeasureSpec is in the vertical direction, and the Measure specified by the parent view on the control */public final void measure (int widthMeasureSpec, int heightMeasureSpec) {... onMeasure (widthMeasureSpec, heightMeasureSpec );...} protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension (getDefaultSize (partition (), widthMeasureSpec), getDefaultSize (partition (), heightMeasureSpec ));}
4. layout related concepts and core methods

First of all, it should be clear that the specific position of the Child view is relative to that of the parent view. The onLayout method of View is empty, while the onLayout method of ViewGroup is abstract. Therefore, if a custom View inherits the ViewGroup, The onLayout function must be implemented.

During layout, the Child view callsgetMeasuredWidth()AndgetMeasuredHeight()Method to obtain the mMeasuredWidth and mMeasuredHeight obtained by the measure process, as their own width and height. Then, calllayout(l, t, r, b)Function to determine the position of each child view in the parent view.

OnLayout source code analysis of LinearLayout

@ Override protected void onLayout (boolean changed, int l, int t, int r, int B) {if (mOrientation = VERTICAL) {layoutVertical (l, t, r, b);} else {layoutHorizontal (l, t, r, B);}/*** traverse all the child views, set the coordinates of the parent view */void layoutVertical (int left, int top, int right, int bottom) {for (int I = 0; I <count; I ++) {final View child = getVirtualChildAt (I); if (child = null) {childTop + = measureNull Child (I);} else if (child. getVisibility ()! = GONE) {// set the View that does not need to be displayed immediately to GONE to accelerate final int childWidth = child. getMeasuredWidth (); // The Width final int childHeight = child. getMeasuredHeight (); // The height determined by the measure process... determine the values of childLeft and childTop: setChildFrame (child, childLeft, childTop + getLocationOffset (child), childWidth, childHeight); }}} private void setChildFrame (View child, int left, int top, int width, int height) {child. layout (left, top, left + width, top + height);} View. java public void layout (int l, int t, int r, int B ){... setFrame (l, t, r, B)}/*** sets the coordinates relative to the parent View */protected boolean setFrame (int left, int top, int right, int bottom ){...}
5. Draw process related concepts and core methods

Let's take a look at the functions related to the draw process:

  • View. draw (Canvas canvas): Because ViewGroup does not repeat this method, all views are drawn by calling the draw method of View. In a custom view, this method should not be rewritten, but be rewritten.onDraw(Canvas)Method. If the custom view does need to re-write the method, callsuper.draw(canvas)Complete the system painting and then customize the painting.

  • View. onDraw ():
    ViewonDraw(Canvas)The default value is empty. You need to rewrite the custom rendering process to draw your own content.

  • DispatchDraw () is used to draw child views. By default, the View is empty, and the ViewGroup is rewritten.dispatchDraw()To draw its subviews. We don't need to worry about this method. The custom ViewGroup should notdispatchDraw().

Flowchart

-View. draw (Canvas) Source Code Analysis

/*** Manually render this view (and all of its children) to the given Canvas. * The view must have already done a full layout before this function is * called. when implementing a view, implement * {@ link # onDraw (android. graphics. canvas)} instead of overriding this method. * If you do need to override this method, call the superclass version. ** @ param canvas The Canvas to which the View is rende Red. ** automatically renders a View (including all its child views) based on the given Canvas ). You must complete layout before calling this method. When you customize a view, * You should implement the onDraw (Canvas) method instead of the draw (canvas) method. If you do need to re-write this method, remember to call the method of the parent class first. */Public void draw (Canvas canvas) {/* Draw traversal performs several drawing steps which must be executed * in the appropriate order: ** 1. draw the background if need * 2. if necessary, save the canvas 'layers to prepare for fading * 3. draw view's content * 4. draw children (dispatchDraw) * 5. if necessary, draw the fading edges and restore layers * 6. draw decorations (scrollbars for insta Nce) * // Step 1, draw the background, if needed if (! DirtyOpaque) {drawBackground (canvas);} // skip step 2 & 5 if possible (common case) final int viewFlags = mViewFlags; if (! VerticalEdges &&! HorizontalEdges) {// Step 3, draw the content if (! DirtyOpaque) onDraw (canvas); // Step 4, draw the children dispatchDraw (canvas); // Step 6, draw decorations (scrollbars) onDrawScrollBars (canvas); if (mOverlay! = Null &&! MOverlay. isEmpty () {mOverlay. getOverlayView (). dispatchDraw (canvas);} // we're done... return;} // Step 2, save the canvas 'layers... // Step 3, draw the content if (! DirtyOpaque) onDraw (canvas); // Step 4, draw the children dispatchDraw (canvas); // Step 5, draw the fade effect and restore layers // Step 6, draw decorations (scrollbars) onDrawScrollBars (canvas );}

From the above process, we can also draw some optimization tips: When you do not need to draw a Layer, the second and fifth steps will skip. Therefore, you can save layers as much as you can, and increase the rendering efficiency.

ViewGroup. dispatchDraw () Source Code Analysis

DispatchDraw (Canvas canvas) {... if (flags & FLAG_RUN_ANIMATION )! = 0 & canAnimate () {// process the ChildView animation final boolean buildCache =! IsHardwareAccelerated (); for (int I = 0; I <childrenCount; I ++) {final View child = children [I]; if (child. mViewFlags & VISIBILITY_MASK) = VISIBLE) {// draw only the layout of the Visible State. Therefore, you can use delayed loading to improve the efficiency of final LayoutParams = child. getLayoutParams (); attachLayoutAnimationParameters (child, params, I, childrenCount); // Add the Layout Change animation bindLayoutAnimation (child); // bind the animation if (cache) {Child. setDrawingCacheEnabled (True); if (buildCache) {child. buildDrawingCache (true) ;}}} final LayoutAnimationController controller = mLayoutAnimationController; if (controller. willOverlap () {mGroupFlags | = FLAG_OPTIMIZE_INVALIDATE;} controller. start (); // start the View animation} // draw the ChildView for (int I = 0; I <childrenCount; I ++) {int childIndex = customOrder? GetChildDrawingOrder (childrenCount, I): I; final View child = (preorderedList = null )? Children [childIndex]: preorderedList. get (childIndex); if (child. mViewFlags & VISIBILITY_MASK) = VISIBLE | child. getAnimation ()! = Null) {more | = drawChild (canvas, child, drawingTime );}}...} protected boolean drawChild (Canvas canvas, View child, long drawingTime) {return child. draw (canvas, this, drawingTime);}/*** This method is called by ViewGroup. drawChild () to have each child view draw itself. * This draw () method is an implementation detail and is not intended to be overridden or * to be called from anywhere else other than ViewGroup. drawChild (). */boolean draw (Canvas canvas, ViewGroup parent, long drawingTime ){...}
  • DrawChild (canvas, this, drawingTime)
    Directly calling the Viewchild.draw(canvas, this,drawingTime)In additionViewGroup.drawChild()In addition to methods, you should not repeat or call this method anywhere else. It belongs to ViewGroup. WhileView.draw(Canvas)The method is the method that can be rewritten in the custom control. For details, refer to the aboveview.draw(Canvas). You can see from the parameters,child.draw(canvas, this, drawingTime)It must have processed the logic related to the parent View, but the final drawing of the View is stillView.draw(Canvas)Method.

  • Invalidate ()
    Request to re-paint the View tree, that is, the draw process. If the View Size does not change, it will not be called.layout()And only those calledinvalidate()View of the method.

  • RequestLayout ()
    This method is called when the layout changes, such as the direction and size changes. In a custom view, if you want to re-measure the size in some situations, you should call this method manually. It will triggermeasure()Andlayout()But do not perform draw.

References
How-android-draws
Http://blog.csdn.net/wangjinyu501/article/details/9008271
Http://blog.csdn.net/qinjuning/article/details/7110211
Http://blog.csdn.net/qinjuning/article/details/8074262


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.