2016-11-13 18 views
1

私はAndroidのゲームに問題を思い付いています。ゲームでは、「敵の宇宙船」は、ランダムな時間にレーザー爆弾を撃ちます。したがって、これを行うために乱数を生成するメソッドを作成することにしました。生成された数が4ならば、LaserBlastのArrayListが生成されます。ここでスレッド内のメソッド呼び出しで「スレッド内でハンドラを作成できません」例外が発生する

はメソッドです:

// generates random number which later is used to decide if shoot ot not 
public static void generateRandomNumber(ArrayList<EnemyShipLaserBlast> listOfLaserBlasts) { 
    Random random = new Random(); 
    int number = random.nextInt(30); 

    switch (number) { 
     case 1: 
      break; 
     case 2: 
      break; 
     case 3: 
      listOfLaserBlasts.add(new EnemyShipLaserBlast(5, 3)); 
      Log.i("LASER BLAST WAS ADDED", "**************"); 
      Log.i("size laser blasts " + listOfLaserBlasts.size(), "--------"); 
      break; 
     case 4: 
      break; 

    } 

私は(スレッドによって実行される)run()メソッドからこのメソッドを呼び出すときしかし、私は

java.lang.RuntimeExceptionを得る:CAN がLooper.prepare()を呼び出していないスレッド内でハンドラを作成していません。

run()方法は次のようになります。

@Override 
public void run() { 

    int frames = 0; 
    long startTime = System.nanoTime(); 
    long currTime = 0; 
    long lastTime = System.nanoTime(); 

    while (playing) 
    { 

     currTime = System.nanoTime(); 

     update((currTime - lastTime)/ 1000000000.0f); //updates the game data 
     draw(); //draws the screen based on the game data 
     control(); //controls how long is it until the run() method is called again 

     lastTime = currTime; 

     frames = frames + 1; 
     if (System.nanoTime() - startTime > 100000000) 
     { 
      framesPerSecond = frames; 
      frames = 0; 
      startTime = System.nanoTime(); 
     } 
    } 

} 

だから私は、私はどこか、このメソッドを置くべきか、多分この種の問題を解決する別の方法がある場合は君たちをお願いしたいと思いますか?

+0

を編集し、**全体の**スタックトレースを投稿してください。 – CommonsWare

+1

問題の 'Thread'と' Handler'を作成しているコードを見ることができたら助けになります。 – clownba0t

+0

私は自分の答えを編集しました。うまくいけば助けになるでしょう。 –

答えて

0

更新プログラムを呼び出し、ワーカースレッドから描画します。メインスレッド内からアップデート、描画(およびUIを扱う他のほとんどの関数)を呼び出す必要があります。

あなたはどのようにランナブルに電話しますか?

あなたのHandlerオブジェクトにこのパラメータを追加する必要があります

Looper.getMainLooper() 

だからあなたのハンドラの初期化は、のようになります。

mHandler = new Handler(Looper.getMainLooper()) { 
//your runnable 
} 
+0

もう少し詳しく説明できますか?そして、ああ、私はハンドラオブジェクトを持っていない、または少なくとも私はそれについて知りません... – Kasparas

+0

編集された答え。いくつかの情報が必要です、どのようにあなたのrunnableを呼び出すのですか? – HelloSadness

1

Handler.javaからGUIを更新するには、Androidフレームワークが提供するクラスです。メインスレッド以外のスレッド。

アンドロイドでは、すべてのGUIがメインスレッドで更新されて実行されます。このスレッドには、それ自身に関連付けられた特別なオブジェクトがあります。これはLooperオブジェクトです。ルーパーは、イベントキューを消費し、キュー内のオペレーションを実行する役割を担います。

メインスレッドは、Looper.prepare()を呼び出すことによってLooperのオブジェクトを設定します。任意のスレッドは、Looper.prepare()を呼び出してLooperのオブジェクトを関連付けることができます。

ハンドラオブジェクトがメインスレッド以外のスレッドで作成され、それに関連付けられたルーパオブジェクトを持たない場合、ハンドラのオブジェクトは非常に役に立たない(意図されたタスクを実行できないため行う)。そのhandleMessageメソッドは、フレームワークの規範に従って呼び出されません。 "

メインスレッド以外のスレッド(作成したスレッドから)からGUIを更新したい場合は、Handlerのオブジェクトハンドラオブジェクトはメインスレッドの実行フローパスに作成する必要があります(メインスレッド以外のスレッドの実行メソッドから始まる他のパスからではありません)。このハンドラオブジェクトを使用してsendMessageメソッドを呼び出すことができますオーバーロードされたメソッドは、アンドロイドの開発者サイトで読むことができます)。ハンドラオブジェクトは、GUIを更新できるhandleMessageコールバックを受け取ります。

もっと掘りたい場合は、コードを見て、Handlers、Looper、ThreadLocalについて読むことをお勧めします。これらは内部的にアンドロイドでHandlerの実装に使用されます。

詳細については、https://developer.android.com/training/multiple-threads/communicate-ui.html#Handler

関連する問題