线程中的java方法调用导致“无法在线程内创建处理程序”异常
我正在制作一款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't create handler inside thread that has not called 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();
}
}
}
所以我想问你们,我是否应该把这个方法放在其他地方,或者有其他方法来解决这种问题
# 1 楼答案
您正在从工作线程调用update和draw。您需要从主线程中调用更新、绘制(以及处理UI的大多数其他函数)
你怎么称呼你的runnable
应将此参数添加到处理程序对象:
因此,处理程序初始化类似于:
# 2 楼答案
Handler.java
是android框架提供的一个类,用于从主线程以外的线程更新GUI在android中,所有GUI都在主线程中更新和执行。此线程有一个与自身关联的特殊对象,即
Looper
对象。Looper负责使用事件队列并执行队列中的操作主线程通过调用
Looper.prepare()
来设置Looper的对象。任何线程都可以通过调用Looper.prepare()
来关联Looper的对象如果处理程序对象是在主线程以外的线程中创建的,而主线程没有与之关联的Looper对象,则处理程序对象是毫无用处的(因为它将无法执行它打算执行的任务)。它的
handleMessage
方法将不会按照框架的规范调用。“如果您希望从主线程以外的线程(从您创建的线程)更新GUI,可以通过创建Handler的对象来实现。处理程序对象应该在主线程的执行流路径中创建(而不是从主线程以外的任何线程的run方法开始的任何其他路径)。现在,您可以使用这个处理程序对象来调用sendMessage方法(有各种重载方法,您可以在android开发者站点中读取这些方法)。Handler对象接收一个回调
handleMessage
,您可以在其中更新GUI如果您真的想挖掘更多,那么我建议您查看代码并阅读有关处理程序、Looper和ThreadLocal的内容。这些在android内部用于处理程序实现
更多信息请参见https://developer.android.com/training/multiple-threads/communicate-ui.html#Handler