Android View Refresh mechanism

Source: Internet
Author: User

One: General description

In the Android layout system, the parent view is responsible for refreshing and layout the child view, and when the child view needs to be refreshed, the parent view is notified to complete.

Two: Code Analysis

1). ViewGroup AddView method to understand the meaning and transfer of parameters

Invalidat e method to call the parent Class View

Addviewinner methods The main thing to do is

View's Dispatchattachedtowindow (attachinfo info, int visibility) method

1). View's invalidate method, which is a process of backtracking from the next, and the parent view of each layer intersects its own display area with the incoming refresh rect.

void Invalidate (Boolean Invalidatecache) {
if (viewdebug.trace_hierarchy) {
Viewdebug.trace (this, ViewDebug.HierarchyTraceType.INVALIDATE);
}
if (Skipinvalidate ()) {
Return
}
if (Mprivateflags & (Drawn | has_bounds) = = (Drawn | Has_bounds) | |
(Invalidatecache && (mprivateflags & drawing_cache_valid) = = Drawing_cache_valid) | |
(Mprivateflags & invalidated)! = invalidated | | Isopaque ()! = Mlastisopaque) {
Mlastisopaque = Isopaque ();
Mprivateflags &= ~drawn;
Mprivateflags |= DIRTY;
if (Invalidatecache) {
Mprivateflags |= invalidated;
Mprivateflags &= ~drawing_cache_valid;
}
final Attachinfo ai = mattachinfo;
Final viewparent p = mparent;

//noinspection pointlessbooleanexpression,constantconditions
if (! Hardwarerenderer.render_dirty_regions) {
if (P! = NULL && AI! = null && ai.mhardwareaccelerated) {
//Fast-track for gl-enabled applications; Just invalidate the whole hierarchy
//With a null dirty rect, which tells the viewancestor to redraw everything
P.invalidatechild (this, null);
return;
                }
            }
if (P! = NULL && AI! = null) {
                final Rect r = ai.mtmpinvalrect;
R.set (0, 0, Mright-mleft, mbottom-mtop);
Don ' t call invalidate – we don ' t want to internally scroll
Our own bounds
P.invalidatechild (this, r);//The method that calls the subclass completes

            }
        }
    }

2) Invalidatechild method of Viewgrop

Public final void Invalidatechild (View child, final Rect dirty) { Viewparent parent = this;
final Attachinfo attachinfo = mattachinfo; if (attachinfo! = null) {final int[] location = attachinfo.minvalidatechildlocation;

//The location of the child view that needs to be refreshed       Location[child_left_index] = child.mleft;Location[child_top_index] = child.mtop;
//If The child is drawing a animation, we want to copy this flag ontoOurselves and the parent to make sure the invalidate request goes through final Boolean drawanimation = (child.m Privateflags & draw_animation) = = Draw_animation;
Check whether the child, requests the invalidate is fully opaque final Boolean isopaque = Child.isopaque () & amp;&!drawanimation && child.getanimation ()! = NULL;

Mark the child as dirty, using the appropriate flag//Make sure we don't set both flags at the same time Final int opaqueflag = Isopaque? Dirty_opaque:dirty;
Do {View view = null;            if (parent instanceof view) {view = (view) parent; }
if (drawanimation) {if (view! = null) {view.mprivateflags |= draw_animation;                } else if (parent instanceof Viewroot) {((viewroot) parent). Misanimating = true; }            }
If The parent is a dirty opaque or not dirty, mark it dirty with the opaque//flag coming from the                That initiated the invalidate if (view! = null && (View.mprivateflags & dirty_mask)! = DIRTY) { View.mprivateflags = (view.mprivateflags & ~dirty_mask) |            Opaqueflag; }
          parent = parent.invalidatechildinparent (location, dirty);} while (parent! = NULL); }}

Public viewparent invalidatechildinparent (final int[] location, final Rect dirty) {
if ((Mprivateflags & drawn) = = drawn) {
if (Mgroupflags & (Flag_optimize_invalidate | Flag_animation_done))! =
Flag_optimize_invalidate) {

//Offset Refresh area According to the location of the parent view
Dirty.offset (Location[child_left_index]-MSCROLLX, Location[child_top_index]-mscrolly);


Final int left = Mleft;
Final int top = Mtop;

         //Calculate the actual refresh area
if (dirty.intersect (0, 0, mright-left, mbottom-top) | |
(Mprivateflags & draw_animation) = = draw_animation) {
Mprivateflags &= ~drawing_cache_valid;

Location[child_left_index] = left;
Location[child_top_index] = TOP;
return mparent;
}
} else {
Mprivateflags &= ~drawn & ~drawing_cache_valid;

Location[child_left_index] = Mleft;
Location[child_top_index] = mtop;

Dirty.set (0, 0, Mright-location[child_left_index),
Mbottom-location[child_top_index]);

return mparent;
}
}

return null;
}

This upward backtracking process is done until the end of the Viewroot, refreshed by viewroot on this final refresh area

Viewroot.java

public void Invalidatechild (View child, Rect dirty) {

}

This view tree is initiated by the draw () method called by the Performtraversals () method of the Viewroot object, and it is worth noting that each time the drawing is initiated, it is not The view of each view tree is redrawn, and only those views that need to be redrawn are redrawn, and the view class internal variable contains a flag bit drawn when the when the view needs to be redrawn, the flag bit is added for that view.


Call Process:

Mview.draw () Start drawing, the Draw () method implements the following functions:

1. Draw the background of the view

2, to show the gradient box to do some preparation operations (see 5, in most cases, do not need to change the gradient box)

3, call the OnDraw () method to draw the view itself (each view needs to overload the method, ViewGroup do not need to implement the method)

4, call the Dispatchdraw () method to draw the child view (if the view type is not viewgroup, that is, does not include a child view, you do not need to overload the method) It is worth stating that The ViewGroup class has rewritten the functionality of the Dispatchdraw (), and the application generally does not need to override the method, but it can overload the parent function to achieve the specific functionality.

The 4.1 Dispatchdraw () method iterates through each child view and calls Drawchild () to re-callback each child view's draw () method (note that this place "needs to be redrawn" View will call the Draw () method). It is worth noting that the ViewGroup class has rewritten the functionality ofdispatch Draw () , and the application generally does not need to override the method, but can overload the parent function to implement the specific function.





Android View Refresh mechanism

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.