It's because when rendering View
s, the ViewGroup
containing the View
s goes through certain steps when mapping out where each view will appear on the screen. The steps a ViewGroup
takes are:
- Measure (the
ViewGroup
measures all of its child views) - Layout (the ViewGroup positions the measured children at their locations on the screen according to their measurements and
ViewGroup.LayoutParams
) - Draw (the views are drawn on screen).
Since the draw step is the last step when rendering View
s on the screen, adding additional View
s at this step of the process could potentially change (invalidate) the entire layout. If you take a look at the source code for ViewGroup
you'll see that making a call to addView(View v)
starts the entire layout process over again:
public void addView(View child, int index, LayoutParams params) {
if (DBG) {
System.out.println(this + " addView");
}
// addViewInner() will call child.requestLayout() when setting the new LayoutParams
// therefore, we call requestLayout() on ourselves before, so that the child's request
// will be blocked at our level
requestLayout();
invalidate(true);
addViewInner(child, index, params, false);
}
Also, when the ViewGroup
draws it's child View
s on the screen, it normally iterates through all of the View
s currently added to the ViewGroup
. So, if this type of event were to be dispatched during a draw method, it could potentially cause the ViewGroup to attempt drawing a View
that hasn't gone through the necessary steps for rendering yet.
As for related methods, these would essentially be methods that would invalidate the ViewGroup
's the current drawing operation.
Edit:
The SurfaceHolder.Callback methods are just Interface
methods for tracking the state of your drawing surface or SurfaceView/GLSurfaceView. Since the state of the layout should remain constant until the Draw step has finished, there shouldn't really be a need to call this method at that point in the process. However, since these methods are basically Interface methods that YOU implement (they're empty by default in the source), there shouldn't really be a reason why calling one of these methods should cause an error, even though I'm not sure that it would be appropriate to do so. One case that would case an issue would be if your underlying implementation leads to issues like the one I explained above...