Thread中的方法调用给出了“无法在线程内创建处理程序”异常

时间:2016-11-13 13:18:17

标签: java android multithreading exception

我正在制作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()方法(由Thread运行)调用此方法时,我得到了

  

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();
        }
    }

}

所以我想问你们,我是否应该把这个方法放在其他地方,或者是否有另一种方法来解决这类问题?

2 个答案:

答案 0 :(得分:1)

Handler.java是一个由android框架提供的类,用于从主线程以外的线程更新GUI。

在android中,所有GUI都在主线程中更新并执行。该线程有一个与其自身关联的特殊对象,即Looper对象。 Looper负责使用事件队列并执行队列中的操作。

主线程通过调用Looper.prepare()来设置Looper的对象。任何线程都可以通过调用Looper.prepare()来关联Looper的对象。

如果在主线程以外的线程中创建了Handler对象,而该线程中没有与之关联的Looper对象,则处理程序的Object非常无用(因为它无法执行预期的任务)去做)。它的handleMessage方法不会按照框架的规范调用。“

如果您希望从主线程以外的线程(从您创建的线程)更新GUI,您可以通过创建Handler对象来完成此操作。应该在主线程的执行流路径中创建处理程序对象(而不是从除主线程以外的任何线程的run方法开始的任何其他路径)。您现在可以使用此Handler对象来调用sendMessage方法(有各种重载方法,您可以在Android开发人员站点中阅读)。处理程序对象接收回调handleMessage,您可以在其中更新GUI。

如果您真的想挖掘更多,那么我建议您查看代码并阅读有关Handlers,Looper和ThreadLocal的内容。这些内部用于android内部的Handler实现。

请参阅https://developer.android.com/training/multiple-threads/communicate-ui.html#Handler

答案 1 :(得分:0)

您正在调用更新并从工作线程中进行绘制。您需要从主线程中调用更新,绘制(以及处理UI的大多数其他函数)。

你怎么称呼你的可运行的?

您应该将此参数添加到Handler对象:

while(str[i] != '\0')

因此,您的处理程序初始化将类似于:

Looper.getMainLooper()