Suragch
Suragch

Reputation: 511786

Why is onDraw() called continuously?

I noticed in my app that the onDraw() for my custom view was getting called constantly. I thought it was a problem with my code so I made the simplest test app I could. Still, onDraw() is being continuously called.

Here is the activity:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

And the custom view:

public class MyEditText extends EditText {

    int counter=0;

    // Constructors
    public MyEditText(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    public MyEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public MyEditText(Context context) {
        super(context);
    }


    @Override
    protected void onDraw(Canvas canvas) {

        counter++;
        Log.i("Test", Integer.toString(counter));
    }
}

Here is the stack trace when pausing within onDraw():

test [Android Application]  
DalvikVM [localhost:8693]   
    Thread [<1> main] (Suspended (breakpoint at line 29 in MyEditText)) 
        <VM does not provide monitor information>   
        MyEditText.onDraw(Canvas) line: 29  
        MyEditText(View).draw(Canvas) line: 13577   
        MyEditText(View).getDisplayList(DisplayList, boolean) line: 12528   
        MyEditText(View).getDisplayList() line: 12572   
        MyEditText(View).draw(Canvas, ViewGroup, long) line: 13301  
        RelativeLayout(ViewGroup).drawChild(Canvas, View, long) line: 3042  
        RelativeLayout(ViewGroup).dispatchDraw(Canvas) line: 2912   
        RelativeLayout(View).getDisplayList(DisplayList, boolean) line: 12526   
        RelativeLayout(View).getDisplayList() line: 12572   
        RelativeLayout(View).draw(Canvas, ViewGroup, long) line: 13301  
        FrameLayout(ViewGroup).drawChild(Canvas, View, long) line: 3042 
        FrameLayout(ViewGroup).dispatchDraw(Canvas) line: 2912  
        FrameLayout(View).draw(Canvas) line: 13580  
        FrameLayout.draw(Canvas) line: 467  
        FrameLayout(View).getDisplayList(DisplayList, boolean) line: 12528  
        FrameLayout(View).getDisplayList() line: 12572  
        FrameLayout(View).draw(Canvas, ViewGroup, long) line: 13301 
        LinearLayout(ViewGroup).drawChild(Canvas, View, long) line: 3042    
        LinearLayout(ViewGroup).dispatchDraw(Canvas) line: 2912 
        LinearLayout(View).getDisplayList(DisplayList, boolean) line: 12526 
        LinearLayout(View).getDisplayList() line: 12572 
        LinearLayout(View).draw(Canvas, ViewGroup, long) line: 13301    
        PhoneWindow$DecorView(ViewGroup).drawChild(Canvas, View, long) line: 3042   
        PhoneWindow$DecorView(ViewGroup).dispatchDraw(Canvas) line: 2912    
        PhoneWindow$DecorView(View).draw(Canvas) line: 13580    
        PhoneWindow$DecorView(FrameLayout).draw(Canvas) line: 467   
        PhoneWindow$DecorView.draw(Canvas) line: 2284   
        PhoneWindow$DecorView(View).getDisplayList(DisplayList, boolean) line: 12528    
        PhoneWindow$DecorView(View).getDisplayList() line: 12572    
        HardwareRenderer$Gl20Renderer(HardwareRenderer$GlRenderer).draw(View, View$AttachInfo, HardwareRenderer$HardwareDrawCallbacks, Rect) line: 1168 
        ViewRootImpl.draw(boolean) line: 2221   
        ViewRootImpl.performDraw() line: 2093   
        ViewRootImpl.performTraversals() line: 1904 
        ViewRootImpl.doTraversal() line: 1070   
        ViewRootImpl$TraversalRunnable.run() line: 4296 
        Choreographer$CallbackRecord.run(long) line: 725    
        Choreographer.doCallbacks(int, long) line: 555  
        Choreographer.doFrame(long, int) line: 525  
        Choreographer$FrameDisplayEventReceiver.run() line: 711 
        Handler.handleCallback(Message) line: 615   
        Choreographer$FrameHandler(Handler).dispatchMessage(Message) line: 92   
        Looper.loop() line: 137 
        ActivityThread.main(String[]) line: 4914    
        Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]  
        Method.invoke(Object, Object...) line: 511  
        ZygoteInit$MethodAndArgsCaller.run() line: 808  
        ZygoteInit.main(String[]) line: 575 
        NativeStart.main(String[]) line: not available [native method]  
    Thread [<10> Binder_2] (Running)    
    Thread [<9> Binder_1] (Running) 

There are lots of similarly titled questions to mine on SO but only one gave a possible answer: https://stackoverflow.com/a/7741500/3681880

They said:

There isn't an infinite loop here. What is going on is the OS is redrawing your activity as fast as possible.

Is that true? Isn't that bad for performance or battery life or something? And why would you ever have to call invalidate() if the system is just calling onDraw() automatically?

Upvotes: 1

Views: 2618

Answers (2)

davnig
davnig

Reputation: 342

Had the same problem. Another possible reason of infinite looping of onDraw() method, is when you use a GlobalLayoutListener with onGlobalLayout() performing some action with your custom view onDraw() method in some way, and you don't remove it.

Upvotes: 0

Suragch
Suragch

Reputation: 511786

As @southerton mentioned in the comments above, the EditText needs to invalidate itself indefinitely in order to animate its cursor.

Upvotes: 1

Related Questions