onDraw happening all the time

I have a simple tabbed component screen.  The current tab just has a text editor and a bunch of buttons.  My code is only called on a button-press.

For some reason, I'm getting a continuous stream of 'onDraw' calls (and a ton of messages posted).  This appears to be the reason for the very laggy response when clicking a button.

An excerpt from my (logging version of) StartActivity):

I/8th:StartActivity( 8329): onDraw: 337 at: 1427269173723

I/8th:StartActivity( 8329): postMessage: 1759126408 at 1427269174093

I/8th:StartActivity( 8329): postMessage: 1520680904 at 1427269174097

I/8th:StartActivity( 8329): postMessage: 1618209744 at 1427269174338

I/8th:StartActivity( 8329): postMessage: 1621131664 at 1427269174338

I/8th:StartActivity( 8329): onDraw: 335 at: 1427269174108

I/8th:StartActivity( 8329): postMessage: 1759126408 at 1427269174475

I/8th:StartActivity( 8329): postMessage: 1759126408 at 1427269174777

I/8th:StartActivity( 8329): onDraw: 356 at: 1427269174474

I/8th:StartActivity( 8329): postMessage: 1520680904 at 1427269174871

etc.... 

the onDraw takes a third of a second to complete, and my code isn't even getting called.  That's entirely inside Juce.

I also timed my keyboard callbacks handler, that only takes 1 or 2 milliseconds; plenty reactive enough.

Hi ronaaron, I've been trying to reproduce your bug in the iOS simulator. I essentially created a new GUI app in the Introjucer and added a TabbedComponent to the default template of MainComponent.cpp:


MainContentComponent::MainContentComponent ()
{
    addAndMakeVisible (tabbedComponent = new TabbedComponent (TabbedButtonBar::TabsAtTop));
    tabbedComponent->setTabBarDepth (30);
    tabbedComponent->addTab (TRANS("Tab 0"), Colours::lightgrey, new MyTabComponent(), true);
    tabbedComponent->addTab (TRANS("Tab 1"), Colours::lightgrey, 0, false);
    tabbedComponent->addTab (TRANS("Tab 2"), Colours::lightgrey, 0, false);
    tabbedComponent->setCurrentTabIndex (0);

    //[UserPreSize]
    //[/UserPreSize]
    setSize (600, 400);

    //[Constructor] You can add your own custom stuff here..
    //[/Constructor]
}

I created the "MyTabComponent" referred to above in the Introjucer with "Add new GUI Component..." and simply added a textbox and four buttons. Running this in the simulator responded fine and didn't have any excessive calls to draw. Any pointers you can give me to reproduce this?

Well, its an Android problem, not an iOS problem.

I don't have the issue on any platform but Android.

Were you able to repro on Android?

I should have inferred from your log output that you are on android.

However, I was still unable to reproduce your bug - both on the android emulator and on a physical device (Samsung Galaxy Nexus). Obviously, when the text editor was active, there would be an onDraw every time the I-beam blinks - this is expected behaviour and should not be the cause of slow responsiveness. 

Even if the edit is not focused (a button is focused, instead) the onDraw happens all the time.  They take 300 msec every time ...

If I unfocus the text box I see no onDraw events. Just to be sure that the TabComponent is really the issue: can you start with a fresh GUI application template and then modify the template as I described above?

I'm using JUCE in a non-standard way; so perhaps that's part of the issue if you don't see it.  Still don't know why platforms other than Android would not exhibit the problem (with my usage).

I'll investigate it further later on.  Thanks.

OK.  So I realized (duh) that the onDraw happening was because I have a thread which updates a clock on the screen, once a second.  When I removed that code, the onDraw stopped happening (when the text box was not focused).  So far, that's good.

However, the 'onDraw' still takes more than a third of a second to complete ... and that's all inside JUCE, not my code (which isn't called on draw).

This is a Nexus 7 tablet, so the screen is pretty large; I assume that there is something perhaps with screen buffering?  The lag is extremely noticeable when pressing a key (until the key-press shows up in the text edit for instance). 

Any help will be most appreciated, as this is a real problem for me.

In desperation, I reviewed the manifest; when I changed the target sdk versions to match the ones in the introjuicer, lo and behold! things are much (!!!!) better.

I had 9 as the minimum sdk, now it's 10.  Could that be the cause of so much grief?

I've been told by android developers that using 10 as the minimum sdk is a sensible choice both because Google fixed a lot of performance bugs and also because anything less has an insignificant market share anyways. Api level 10 corresponds to gingerbread and anything older than gingerbread has a marketshare of less than 0.6%:

http://www.appbrain.com/stats/top-android-sdk-versions

This is the reason why the minimum sdk is set to 10 by default in the Introjucer.

 

 

IF you are using the OpenGL renderer, this is what I have done to deal with this (as mentioned on another thread).  And if you are *not* using the OpenGL renderer, you want to, especially with recent high-pixel-density devices. Here is my quote from that thread:

"There is an issue in the current JuceAppActivity java template when using an OpenGL context that leads to terrible touch event performance.  In the ComponentPeerView inner class, the onDraw() gets called by the runtime on every touch down event, and handlePaint (a native method) is called.  But the problem is that when it has added a GL context, the handlePaint() attempts to render in the *software rendering* pipeline causing massive slowdowns.  I added an additional boolean state to ComponentPeerView to keep track of when an OpenGL context was added (in its createGLView() method), and if so, *do not* call handlePaint, because it is unnecessary for the GL renderer.

I don't know why the java runtime is calling the onDraw method on touch down events in the first place, but it seems like a bad idea regardless.  Preventing onPaint from being called was critical when GL is the context, though.  Basically, if it is an openGL context, just doing nothing in  onDraw() has no adverse effect on the graphics of the app."

 

Here are the links to the other threads where I think a related thing was reported:

http://www.juce.com/forum/topic/opengl-render-android

http://www.juce.com/forum/topic/juce-receives-first-touch-event-very-late

 

I'm not using OpenGL; it's just simple app stuff (buttons etc).  Would there be any benefit for me using OpenGL?  Any down side?

I found using OpenGL dramatically improved performance of my app, in terms of frame rate  - its reacting to audio input, and is about 10x faster with OpenGL.

Its also should give much better performance with hi res screens.

However there is currently an issue with the HTC Desire which, at least on my device, causes extreme glitches when using OpenGL. I'm currently working around it by detecting the device name before I attach the OpenGL context.