2016-11-13 39 views
1

我正在製作Android遊戲時出現了問題。在這個遊戲中,「敵方太空船」將在隨機時間發射激光爆炸。因此,爲了做到這一點,我決定創建一個生成隨機數的方法,如果生成的數字是4,那麼將填充LaserBlasts的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:能在線程中創建處理程序, 尚未調用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的大多數其他函數)。

你怎麼稱呼你的runnable?

您應將此參數添加到您的處理對象:

Looper.getMainLooper() 

所以,你的處理程序初始化會是這樣的:

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

你能解釋我多一點嗎?而且,我沒有任何處理程序對象,或者至少我不知道它... – Kasparas

+0

已編輯的答案。需要更多的信息,你怎麼稱呼你的runnable? – HelloSadness

1

Handler.java是由Android框架提供的類來更新從GUI主線程以外的線程。

在android中,所有GUI都在主線程中更新和執行。該線程有一個與自身關聯的特殊對象,即Looper對象。 Looper負責使用事件隊列並執行隊列中的操作。

主線程通過調用Looper.prepare()來設置Looper的對象。任何線程都可以通過調用Looper.prepare()來關聯Looper的一個對象。

如果Handler對象是在除了主線程之外的Thread線程中創建的,而Thread線程沒有與其關聯的Looper對象,那麼Handler對象是無用的(因爲它無法執行它打算的任務做)。 「

如果您希望從主線程以外的線程(從您創建的線程)更新GUI,您可以通過創建一個Handler對象來完成此操作。Handler對象應該在主線程的執行流程路徑中創建(不是從主線程以外的任何線程的run方法開始的任何其他路徑)。現在可以使用此Handler對象來調用sendMessage方法(有各種重載的方法,你可以在android的開發者站點閱讀)Handler對象接收一個回調handleMessage,你可以在其中更新GUI。

如果你真的想挖掘更多,那麼我建議你看看代碼並閱讀Handlers,Looper和ThreadLocal。這些內部用於android內部的Handler實現。

更多請參考https://developer.android.com/training/multiple-threads/communicate-ui.html#Handler

相關問題