Question

In Android documentation, it says the following for addView (and a few other methods):

Note: do not invoke this method from draw(android.graphics.Canvas), onDraw(android.graphics.Canvas), dispatchDraw(android.graphics.Canvas) or any related method.

What's the reason for this restriction? Also, what are the "related methods"? For instance, is surfaceChanged such method?

Was it helpful?

Solution

It's because when rendering Views, the ViewGroup containing the Views goes through certain steps when mapping out where each view will appear on the screen. The steps a ViewGroup takes are:

  1. Measure (the ViewGroup measures all of its child views)
  2. Layout (the ViewGroup positions the measured children at their locations on the screen according to their measurements and ViewGroup.LayoutParams)
  3. Draw (the views are drawn on screen).

Since the draw step is the last step when rendering Views on the screen, adding additional Views 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 Views on the screen, it normally iterates through all of the Views 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...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top