2016-11-13 38 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

相关问题