Reputation: 89
I am making an Android game a came up with a problem. In the game "enemy space ships" will be shooting laser blasts at a random time. Therefore in order to do this I have decided to make a method that generates a random number and if the number generated is 4 then an ArrayList of LaserBlasts will be populated.
Here is the method:
// 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;
}
However, when I call this method from run()
method (which is run by the Thread) I get a
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare().
My run()
method looks like this:
@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();
}
}
}
So I would like to ask you guys if i should put this method somewhere else or maybe there is another way to fix this kind of problem?
Upvotes: 1
Views: 96
Reputation: 5316
Handler.java
is a class provided by android framework to update the GUI from threads other than main Thread.
In android all the GUI is updated and executed in the Main thread. This thread has an special object associated with itself which is Looper
object. Looper is responsible for consuming the event queue and executing the operations in the queue.
Main thread sets the object of Looper by calling Looper.prepare()
. Any thread can associate an object of Looper by calling Looper.prepare()
.
If Handler object is created in a Thread other than main Thread which does not have object of Looper associated with it, then Object of handler is quite useless (as it will not be able to perform the task it is intended to do). Its handleMessage
method will not be called as per the norms of the framework."
If you wish to update GUI from thread other than Main thread (from the thread you created) you can do this by creating an object of Handler. Handler object should be created in the execution flow path of Main thread (not from any other path which is starting from run method of any thread other than Main thread). You can now use this Handler object to invoke sendMessage methods (there are various overloaded methods, which you can read in developers site for android). Handler object recieves a call back handleMessage
in which you can update the GUI.
If you really want to dig more then I suggest you to see the code and read about Handlers, Looper and ThreadLocal. These are internally used for Handler implementation internally in android.
Refer more at https://developer.android.com/training/multiple-threads/communicate-ui.html#Handler
Upvotes: 1
Reputation: 955
You're calling update and draw from a worker thread. You need to call updates, draw (and most other functions dealing with the UI) from within the main thread.
How do you call your runnable ?
You should add this parameter to your Handler object :
Looper.getMainLooper()
So your Handler initialization would be something like :
mHandler = new Handler(Looper.getMainLooper()) {
//your runnable
}
Upvotes: 0