mcccclean
mcccclean

Reputation: 7931

Why are touch events destroying my Android framerate?

I'm developing a game for Android. It's got a lot going on but is running reasonably smoothly. That is, of course, until the user touches the screen.

While they're touching it, onTouchEvent is called (with action = ACTION_MOVE, x = 0 and y = 0) roughly once every ten milliseconds at what appears to be a fairly high priority, as it absolutely obliterates the framerate. As soon as the touch ends the framerate returns to its nice state.

I've tried

The problem persists in all three situations.

Has anyone encountered this? Is there a way to reduce the rate at which ACTION_MOVE events are generated, or to ensure that they're only generated when there is actual movement, or use a polling method that just gets the current location of the touch? Or even just a way to disable it entirely?

Upvotes: 15

Views: 11997

Answers (5)

h.martin
h.martin

Reputation: 61

Generally events comes with a timestamp property so it's easy to compute and throttle event rate.

if (currentEventTimestamp - lastEventTimestamp > 500) { 

    lastEventTimestamp = currentEventTimestamp;

    // do something 

}

Upvotes: 0

Björn Harrtell
Björn Harrtell

Reputation: 211

If you want a solution without having to deal with synchronizing threads I can recommend using the Handler interface to send the event and relevant data using a Message/Bundle to the game rendering thread. The sleep workaround hinted here still applies.

Upvotes: 0

Damocles
Damocles

Reputation: 11

I've been trying to follow everything you guys have been talking about, but I must admit that after trying several ways of implementing what you suggest, I still haven't been able to achieve any positive results. Could one of you provide some example code? Specifically, I'd like to know how to go about making the main/UI thread sleep. If it's applicable to my games, it would also be nice to know how to set up a polling model like Jon implemented.

Here's what my code looks like. On the UI thread:

public boolean onTouchEvent(MotionEvent event) {
    // Store event somewhere the game thread can see it:
    // ...

    synchronized (someObject) {
        try {
            someObject.wait(1000L);
        } catch (InterruptedException e) {
        }
    }

    return true;
}

and on the Game thread:

void myGame() {
    while (!stopping) {
        // ...

        // Get a touch event:
        synchronized (someObject) {
            someObject.notify();
        }
        Thread.yield();

        // ...
    }
}

Upvotes: 1

hacken
hacken

Reputation: 2145

Read this thread. Basically you want to sleep the event thread since otherwise the system will pump a lot of events (between x,y and pressure there is always some movement going on) that you need to handle.

Upvotes: 14

pjz
pjz

Reputation: 43117

Perhaps a somewhat obvious solution, but... have you tried only handling about 1/10 of them? If you're doing processing that's triggered every 10ms on the UI thread, that's likely going to slow down the framerate, yes. So what if you just accumulate a counter somewhat instead and only do any processing once that's gotten past some minimal threshold?

Upvotes: 0

Related Questions