Android interview, View rendering process, invalidate () and other related Methods Analysis, androidinvalidate
The drawing process of the entire View tree is expanded in the javasmtraversals () function of the ViewRoot. java class. The execution process of this function is as follows:
Determine whether to recalculate the View Size (measure), whether to relocate the view location (layout), and whether to re-paint the view based on the previously set status.
(Draw), the Framework process is as follows:
Measure () Process
Main function: calculate the actual size for the entire View tree, that is, set the actual height (corresponding attribute:MMeasuredHeight) And width (corresponding property:MMeasureWidth), The actual width and height of each View control are determined by the parent View and its own View.
The call chain is as follows:
The ViewRoot root object property mView (whose type is generally ViewGroup) calls the measure () method to calculate the size of the View tree, and calls back the onMeasure () method of the View/ViewGroup object.The functions implemented by this method are as follows:
1. Set the final size of the View. This function is implemented by calling the setMeasuredDimension () method to set the actual height (corresponding attribute: mMeasuredHeight) and width (corresponding attribute: mMeasureWidth );
2. If the View object is of the ViewGroup type, you must override the onMeasure () method to traverse the measure () process of its subviews.
2.1 The measure () process for each sub-view is by calling the parent class ViewGroup. the measureChildWithMargins () method in the java class is implemented. This method simply calls the measure () method of the View object. (Because the measureChildWithMargins () method is only a simple method of transition layer, it is to directly call the measure () method of the View object ).
The entire measure call process is a tree-like recursive process.
Measure function prototype is View. java. This function cannot be overloaded.
Public final void measure (int widthMeasureSpec, int heightMeasureSpec) {//... // callback onMeasure () method onMeasure (widthMeasureSpec, heightMeasureSpec); // more}
For better understanding, we use the "B programmer" method to describe the measure Process Using Pseudo code.
// Call back the onMeasure process private void onMeasure (int height, int width) in the View. {// set the actual width (mMeasuredWidth) of the view to mMeasuredHeight) // 1. This method must be called in onMeasure. If not, an exception is reported. SetMeasuredDimension (h, l); // 2. If the View is of the ViewGroup type, perform the measure () process int childCount = getChildCount () for each of its child views (); for (int I = 0; I <childCount; I ++) {// 2.1, get each child View object reference View child = getChildAt (I); // The entire measure () A process is a recursive process // This method is only a filter, and the measure () process is called at last; or the measureChildWithMargins (child, h, I) methods are all measureChildWithMargins (child, h, i); // In fact, the best way for applications we write is to remove the method in the framework and directly call view. measure (), as follows: // child. measure (h, l ) }}// The method is implemented in ViewGroup. java. Protected void measureChildWithMargins (View v, int height, int width) {v. measure (h, l )}Layout Process
Main function: to place the View tree in a proper position based on the size and layout parameters of the subview
The call chain is as follows:
Host. layout () starts the layout of the View tree and calls back the layout () method in the View/ViewGroup class.. The procedure is as follows:
1. The layout method sets the coordinate axes of the View in the parent View, that is, mLeft, mTop, mLeft, and mBottom (implemented by calling the setFrame () function). Next, it calls back onLayout () method (if the View is a ViewGroup object, you need to implement this method to layout each subview );
2. If the View is of the ViewGroup type, you need to traverse each sub-View, and call the layout () method of the sub-View to set its coordinate value.
The original layout function is located in View. java
/* Final identifier, which cannot be overloaded. The parameter is the coordinate axis * @ param l Left position, relative to parent * @ param t Top position of each view, relative to parent * @ param r Right position, relative to parent * @ param B Bottom position, relative to parent */public final void layout (int l, int t, int r, int B) {boolean changed = setFrame (l, t, r, B); // set the axis of each view in the parent view if (changed | (mPrivateFlags & LAYOUT_REQUIRED) = LAYOUT_REQU IRED) {if (ViewDebug. TRACE_HIERARCHY) {ViewDebug. trace (this, ViewDebug. hierarchyTraceType. ON_LAYOUT);} onLayout (changed, l, t, r, B); // calls back the onLayout function and sets the layout of each subview mPrivateFlags & = ~ LAYOUT_REQUIRED;} mPrivateFlags & = ~ FORCE_LAYOUT ;}
Similarly, the preceding layout call process is described as follows using pseudocode:
// ViewRoot during layout. java // initiate layout () "sender" in ViewRoot. java's javasmtraversals () method, mView. layout () private void extends mtraversals (){//... view mView; mView. layout (left, top, right, bottom );//....} // calls back the onLayout process in the View. This method implements private void onLayout (int left, int top, right, bottom) only by the ViewGroup type) {// if the View is not of the ViewGroup type, // call the setFrame () method to set the coordinate axis setFrame (l, t, r, B) of the control on the parent View ); // ------------------------ // if the View is of the ViewGroup type, the layout () process int childCount = getChildCount (); for (int I = 0; I <childCount; I ++) {// 2.1, get each sub-View object reference View child = getChildAt (I); // The Entire layout () process is a recursive process child. layout (l, t, r, B );}}Drawing Process
Call the draw () method of the ViewRoot object's javasmtraversals () method to draw the View tree. It is worth noting that each time a drawing is initiated, the View of each View tree is not re-drawn, instead, it only re-draws the views that require re-painting. The internal variables of the View class contain a flag DRAWN. When the View needs to be re-painted, the flag is added to the View.
Call process:
MView. draw () starts to draw. The functions implemented by the draw () method are as follows:
1. Draw the background of the View
2. Prepare the gradient box (in most cases, you do not need to change the gradient box)
3. Call the onDraw () method to draw the View itself (this method needs to be reloaded for each View, and ViewGroup does not need to implement this method)
4. Call the dispatchDraw () method to draw a subview (if the View type is not ViewGroup, that is, it does not contain a subview and does not need to be reloaded). It is worth noting that, the ViewGroup class has already rewritten the dispatchDraw () function implementation for us. In general, applications do not need to rewrite this method, but you can reload the parent class function to implement specific functions.
4.1 The dispatchDraw () method traverses each subview and calls drawChild () to call back the draw () method of each subview. (Note, the draw () method is called only for views that require redrawing ). It is worth noting that the ViewGroup class has already rewritten the dispatchDraw () function implementation for us. In general, applications do not need to rewrite this method, but you can override the parent class function to implement specific functions.
Draw a scroll bar
Pseudocode:
// ViewRoot in the draw () process. java // initiate the "poster" of draw () in ViewRoot. java's javasmtraversals () method. This method continues to call the draw () method to start drawing private void draw (){//... view mView; mView. draw (canvas );//....} // calls back the onLayout process in the View. This method is implemented only by the ViewGroup type private void draw (Canvas canvas) {// This method will do the following: // 1. Draw the background of the View. // 2. Prepare the gradient box. // 3. Call onDraw () method to draw the view itself // 4. Call the dispatchDraw () method to draw each sub-view. dispatchDraw () has been implemented in the Android framework, in the ViewGroup method. // The application generally does not need to override this method, but it can capture the occurrence of this method and do some special things. // 5. Draw a gradient box} // ViewGroup. the dispatchDraw () method in java. Generally, the application does not need to Override this method @ Override protected void dispatchDraw (Canvas canvas) {// Its implementation method is similar to the following: int childCount = getChildCount (); for (int I = 0; I <childCount; I ++) {View child = getChildAt (I); // call drawChild to complete drawChild (child, canvas) ;}// ViewGroup. the dispatchDraw () method in java. Generally, the application does not need to override this method protected void drawChild (View child, Canvas canvas ){//.... // simple callback View object The draw () method of is generated by recursion. Child. draw (canvas );//.........}Invalidate () method
Note: You need to re-paint the View tree, that is, the draw () process. If the View Size does not change, the layout () process will not be called and only the "re-painted" views will be drawn, that is, if a View (View, only the View is drawn; ViewGroup, the entire ViewGroup is drawn), and the View is drawn when the invalidate () method is requested.
Generally, the function that causes the invalidate () operation is as follows:
1. Call the invalidate () method directly and request a new draw (), but only the caller is drawn.
2. setSelection () method: Request re-draw (), but only the caller itself will be drawn.
3. setVisibility () method: When the VISIBLE state of a View is converted to VISIBLE in INVISIBLE, the invalidate () method is called indirectly and the View is drawn.
4. setEnabled () method: request to re-draw (), but will not re-draw any view including the caller itself.
RequestLayout () method
The measure () process and layout () process are called.
Note: The layout process of View tree re-layout includes the measure () and layout () processes. The draw () process is not called, but no View is re-drawn, including the caller.
Generally, the function that causes the invalidate () operation is as follows:
1. setVisibility () method:
The requestLayout () and invalidate methods are called indirectly when the visual status of a View is changed from INVISIBLE to GONE.
At the same time, because the size of the entire View tree has changed, the measure () process and the draw () process will be requested. Similarly, only the View that needs to be "re-drawn" will be drawn.
RequestFocus ()Method
Note: The draw () process of the View tree is requested, but only the View that needs to be re-painted is drawn.
Differences between draw and onDraw in View
1. Scan the source code to understand that the draw () function itself will do a lot of things,
* 1. Draw the background
* 2. If necessary, save the canvas 'layers to prepare for fading
* 3. Draw view's content
* 4. Draw children
* 5. If necessary, draw the fading edges and restore layers
* 6. Draw decorations (scrollbars for instance)
In step 3, it will call the onDraw () method to draw the view content. That is, draw calls onDraw.
You can use onDraw to draw the view content directly. If you want to draw more content, you can call draw (), however, the Android official recommendation only uses onDraw. "When implementing a view, do not override this method; instead, you shoshould implement onDraw"
2. the draw (Canvas canvas) method is called for drawing the View component. In the draw process, the Drawable background is drawn first, and the setBounds () method is called for drawable, followed by the draw (Canvas c) method. note that the actual size of the background drawable will affect the size of the view component. The actual size of the drawable is obtained through getIntrinsicWidth () and getIntrinsicHeight, when the background is large, the size of the view component is equal to the size of the background drawable. After the background is drawn, the draw process calls the onDraw (Canvas canvas) method, and then the dispatchDraw (Canvas canvas) method, dispatchDraw () it is mainly distributed to sub-components for rendering. We usually rewrite the onDraw () method when customizing components. It is worth noting that the ViewGroup container component is drawn. When there is no background, the dispatchDraw () method is called directly, and the draw () method is bypassed, when there is a background, the draw () method is called, while the draw () method contains the call of the dispatchDraw () method. Therefore, the dispatchDraw () method rather than the onDraw () method is often overwritten when drawing things on the ViewGroup, or a Drawable can be customized to override its draw (Canvas c) and getIntrinsicWidth (), getIntrinsicHeight (), and then set it as the background.
3. Differences between ondraw () and dispatchdraw ()
Draw the VIew content by calling the View. onDraw (canvas) function.
Draw your child using dispatchDraw (canvas)
I am the dividing line of tiantiao
Reference: http://blog.csdn.net/qinjuning/article/details/7110211
In android development, does the invalidate () method automatically clear the previous screen?
Invalidate () is used to refresh the View and must work in the UI thread. For example, when you modify the display of a view, call invalidate () to view the re-drawing interface. The call of invalidate () is to pop the old view from the main UI thread queue.
Why can't the code be run when android invalidate () calls onDraw () to reproduce the code?
SetContentView (new View (null ){...}); Change to setContentView (new View (this ){...}); Try.