简体   繁体   English

Android:Touch严重降低了我的应用程序速度

[英]Android: Touch seriously slowing my application

I've been raking my brains on this one for a while. 我一直在这个问题上绞尽脑汁。

when I'm running my application (opengl game) eveyrthing goes fine but when I touch the screen my application slows down quite seriously (not noticeable on powerful phones like the nexus one, but on the htc magic it gets quite annoying). 当我正在运行我的应用程序(opengl游戏)时,eveyrthing正常,但是当我触摸屏幕时,我的应用程序非常严重地减速(在强大的手机上并不明显,例如nexus,但在htc魔术上它变得非常烦人)。

I did a trace and found out that the touch events seem to be handled in a different thread and even if it doesn't take so much processing time I think androids ability to switch between threads is not so good... 我做了一个跟踪,发现触摸事件似乎是在一个不同的线程中处理,即使它没有花费太多的处理时间,我认为orroids在线程之间切换的能力并不是那么好......

What is the best way to handle touch when speed is an issue ? 当速度成为问题时,处理触摸的最佳方法是什么?

Currently I'm using : in the GLSurfaceView 目前我正在使用:在GLSurfaceView中

@Override
 public boolean onTouchEvent(MotionEvent event) {
     GameHandler.onTouchEvent(event);
     return true;
 }

Any ideas are welcome 欢迎任何想法

I have a feeling the bug report below may be relevant. 我有一种感觉,下面的错误报告可能是相关的。 Sadly in seems its only going to be fixed in gingerbread. 可悲的是,它似乎只能在姜饼中修复。

Bug report 错误报告

Have just seen that SO prefers details in the answers in case links vanish etc. the above refers to a google accepted bug in Adnroid 2.1 targetted for a fix in the gingerbread release. 刚刚看到SO更喜欢答案中的细节,以防链接消失等。上面提到了Adnroid 2.1中谷歌接受的bug,目标是在姜饼发布中修复。

Issue 7836: system_server consumes excessive CPU processing touch events 问题7836:system_server消耗过多的CPU处理触摸事件

I can't vouch for this myself, but my research has shown that touching the screen fires so many events that it floods the events queue and therefore lags the CPU taking your resources. 我不能自己担保,但是我的研究表明触摸屏幕会引发很多事件,因为它会淹没事件队列,因此会占用CPU资源。

Try putting: - 尝试放: -

   try {
        Thread.sleep(16);
    } catch (InterruptedException e) {} //ignore

before any returns that you have in the onTouch method (usually there's only the one at the end - but just making sure). 在onTouch方法中有任何返回之前(通常只有最后一个返回 - 但只是确保)。 I know sleep is usually a very bad thing to do, but its not in the UI thread so it should be ok. 我知道睡眠通常是一件非常糟糕的事情,但它不在UI线程中,所以应该没问题。 Sleep 16 should cap the FPS to 60. 睡眠16应该将FPS限制在60。

Don't put heavy computation to your onTouchEvent(). 不要对onTouchEvent()进行繁重的计算。 The OnTouchEvent can be fired tens or hundred of times per second per finger, you should defer the heavy computation to the other part of your game (eg the physics engine or the graphic engine). OnTouchEvent每个手指可以每秒发射数十或数百次,你应该将繁重的计算推迟到游戏的其他部分(例如物理引擎或图形引擎)。 In particular avoid drawing in your onTouchEvent. 特别是避免在onTouchEvent中绘图。

You should preferrably use onClickEvent or other less intensive mouse event and only use onTouchEvent when you really need to track the motion of the touch. 您最好使用onClickEvent或其他不太密集的鼠标事件,并且只有在真正需要跟踪触摸动作时才使用onTouchEvent。

@Jason: @Jason:

This was going to be a comment, but it grew too big and it is a different [better] answer to the one I just gave. 这将是一个评论,但它变得太大了,这是我刚刚给出的一个不同的[更好]答案。

I have changed my implementation using this method as described here http://obviam.net/index.php/the-android-game-loop/ 我使用此方法更改了我的实现,如http://obviam.net/index.php/the-android-game-loop/

By employing the method described above means you should not need to sleep the OnTouch events. 通过使用上述方法意味着您不需要睡眠OnTouch事件。

Also don't forget to protect your game loop thread as mentioned here http://wonton-games.blogspot.com/2010/06/lunar-lander-resume-game-workaround.html 另外不要忘记保护你的游戏循环线程,如http://wonton-games.blogspot.com/2010/06/lunar-lander-resume-game-workaround.html

Also also keep in mind that Chris Pruett when writing Replica Island said he used 2 threads, one for the update() and the other for render() - both will have to be protected. 还要记住,Chris Pruett写Replica Island时说他使用了2个线程,一个用于update(),另一个用于render() - 两者都必须受到保护。

Chris does sleep his OnTouch with 16 milliseconds (60 fps) to cut back the events - so I would say its best to experiment if you still need to cut the events down - you need only touch the screen whilst stuff is happening to see if it lags and thus subsequently speeds up when let go. Chris确实以16毫秒(60 fps)的速度睡眠他的OnTouch以减少事件 - 所以如果你仍然需要减少事件,我会说它最好进行实验 - 你只需触摸屏幕就会发生一些事情,看看它是否有效放手,因此随后放手时加速。

For my needs currently I am using the same thread as I haven't progressed into OpenGL, I still use the canvas. 对于我目前的需求,我使用相同的线程,因为我还没有进入OpenGL,我仍然使用画布。 But when I go OpenGL, it will be 2 threads, and each will be a complete class of its own. 但是当我去OpenGL时,它将是2个线程,并且每个线程都将是它自己的完整类。

Finally, I don't time my sprites by counting frames, I've wrapped them with a timer. 最后,我没有通过计算帧来计算我的精灵,我用计时器包裹它们。 I'll share my Class and show you how I call it. 我将分享我的课程并告诉你我是如何称呼它的。 Bear in mind I am still new to Java so apologies for poor code. 请记住,我仍然是Java的新手,所以对于糟糕的代码道歉。

package com.yourname.yourapplication;

//Used for doing something after a set time
public class TimeDo {
    private int mRepeat = 0; //Stores the last wait period for the reset() later
    private long mTime = 0; //The goal time of when its due
    private boolean mFlagged = false; //Stop them getting a second true on a subsequent check

    public TimeDo(int milliseconds) {
        reset(milliseconds);
    }

    public TimeDo() {
        this(0);
    }

    public void reset(int milliseconds) {
        mRepeat = milliseconds;
        mTime = System.currentTimeMillis() + milliseconds;
        mFlagged = mRepeat==0; //ignore if zero
    }

    public void reset() { //Set it back to the delay used last time 
        reset(mRepeat);
    }

    public boolean check() {
        if (mFlagged) //Assert: shouldn't really happen
            return false;
        mFlagged = System.currentTimeMillis() > mTime; 
        return mFlagged;
    }

    public boolean checkAndReset() {
        if (check()) {
            reset();
            return true;
        }
        return false; //note mFlagged could be true here, so don't use it
    }

}

And it is implemented thusly: - 并由此实施: -

public class Gem {
    private TimeDo mMoveGem = new TimeDo(100); //move 10 times a second, 100ms 
    private int mX = 0;
    private int mY = 0;
    private int mMoveX = 3;
    private int mMoveY = 4;
    .
    .
    .   
    public void update() {
        if (mMoveGem.checkAndReset()) {
            mX += mMoveX;
            mY += mMoveY;
            .
            .
        }
    }

    public void render(Canvas canvas) {
    //etc etc
        .
        .
    }

}

Hope any of that helps! 希望任何有用的! Sorry if you have to rewrite lots of your application - I did. 对不起,如果你必须重写你的许多应用程序 - 我做了。

Edit: That TimeDo class is not a postDelayed runnable, like an automatic alarm. 编辑:那个TimeDo类不是postDelayed runnable,就像一个自动警报。 If you don't check it no "event" will fire. 如果你不检查它,那么“事件”就不会被激活。 You could get excited and have it create a runnable and pass it a callback method that resides within your class (think of an OnClick method) - but defeats the purpose of running an exclusive time-able update() thread that updates all your components. 你可能会兴奋并让它创建一个runnable并传递一个驻留在你的类中的回调方法(想想一个OnClick方法) - 但是无法运行一个更新所有组件的独有的time-able update()线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM