2010-12-03 4 views
2

私はしばらくこの1つ私の脳を掻いてきた。Android:タッチが真剣に私のアプリケーションを遅くする

私のアプリケーション(openglゲーム)を実行しているときにeveyrthingはうまくいくが、画面に触れるとアプリケーションはかなり重大に遅くなる(ネクサス1のような強力な電話では目立たないが、htcの魔法ではかなり迷惑になる)。

私はトレースを行い、タッチイベントが別のスレッドで処理されているように見えます。処理時間があまりかからなくても、スレッド間で切り替えるアンドロイドの能力はあまり良くありません。

スピードが問題になるときにタッチを処理する最も良い方法は何ですか?現在、私が使用している

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

GLSurfaceViewにおけるすべてのアイデアは大歓迎

+0

[なぜ私のAndroidフレームレートを破壊するタッチイベントですか?](http://stackoverflow.com/questions/792185/why-are-touch-events-destroying-my-android-framerate) – richq

答えて

5

以下のバグレポートが適切であると感じています。残念ながら、ジンジャーブレッドで修正されるのは唯一のようです。

Bug report

はちょうどSOリンクは上記などの消えた場合の答えに詳細を好むことを見たことがありAdnroid 2.1のバグを受け入れグーグルを指し、ジンジャーブレッドのリリースで修正のために標的化さ。

問題7836:system_serverは、過度のCPU処理タッチイベント

1

ですが)(あなたのonTouchEventに大量の計算を置かないでください。 OnTouchEventは1指あたり1秒間に数十回または数百回起動できます。重い計算をゲームの他の部分(物理エンジンやグラフィックエンジンなど)に延期する必要があります。特に、onTouchEventを描画しないようにしてください。

あなたは本当にタッチの動きを追跡する必要があるときは、onClickEventまたは他の集中的でないマウスイベントを使用し、onTouchEventのみを使用することをお勧めします。

+0

私は実際に何も重い計算をしていない(通常、私はダブルチェックします)私は位置を収集し、私は画面上でドラッグしているオブジェクトを更新するか、または指がどこに行くかをテストします... –

2

私は、このために自分自身を保証することはできませんを消費しますが、私の研究は、したがって、それはイベントキューをフラッディング画面火災ので、多くのイベントに触れるとは遅れていることを示していますあなたのリソースを取っているCPU。

は入れてみてください: - あなたが( - ちょうど確認して、通常は最後に1つだけあります)onTouch方法を持っている任意の戻り

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

。私は睡眠は通常、非常に悪いことだと知っているが、それはUIスレッドではないので、それは大丈夫です。 16は60

+0

簡単な質問:これ触れられただけですべてのタッチイベントになりますか? –

0

@JasonにFPSをキャップする必要があり、睡眠:

これはコメントになる予定だったが、それはあまりにも大きな成長し、それは私がちょうど与えたものと異なる[より良い]の答えです。上記の方法を採用することにより、ここ http://obviam.net/index.php/the-android-game-loop/

説明したように、私はこの方法を使用して、私の実装を変更した

あなたがOnTouchイベントを寝する必要はありませんを意味します。ここに述べたように

また、あなたのゲームループのスレッドを保護することを忘れないでくださいhttp://wonton-games.blogspot.com/2010/06/lunar-lander-resume-game-workaround.html

もまた、レプリカ島が言っ書くときにクリスPruettは、彼が2つのスレッド、更新のための1()および他のを使用したことを覚えておいてください

render()のためには、両方を保護する必要があります。

クリスはイベントをカットするために16ミリ秒(60fps)で彼のOnTouchを眠っています - それでもイベントをカットする必要がある場合は、実験に最適だと言います - 何かが起きている間は画面に触れるだけですそれが遅れているかどうかを確認して、次に離れるときにスピードアップします。

現在のところ私はOpenGLに進んでいないのと同じスレッドを使用していますが、私はまだキャンバスを使用しています。しかし、私がOpenGLに行くと、2つのスレッドになり、それぞれは完全なクラスになります。

最後に、フレーム数をカウントしてスプライトの時間を計ることはありません。タイマーでラップしました。私はクラスを共有し、私がそれをどのように呼び出すかを示します。私は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 
    } 

} 

そしてそれは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 
     . 
     . 
    } 

} 

は、そのいずれかがお役に立てば幸い! 申し訳ありませんが、あなたのアプリケーションの多くを書き直す必要がある場合 - 私はしました。

編集:そのTimeDoクラスは、自動アラームのように、postDelayedの実行可能ではありません。 をチェックしない場合、にチェックすると「イベント」は発生しません。あなたは興奮して、実行可能ファイルを作成し、クラス内にあるコールバックメソッド(OnClickメソッドを考えてください)を渡すことができます。しかし、すべてのコンポーネントを更新するタイムアウト可能なupdate()スレッドを実行する目的を打ち破ります。

関連する問題