I want to implement a timer in my android game using following code. This code runs certain code after every second.
final Handler handler = new Handler();
Runnable runable = new Runnable() {
#Override
public void run() {
try{
//task to be done
handler.postDelayed(this, 1000);
}
catch (Exception e) {
// TODO: handle exception
}
finally{
//task to be done
handler.postDelayed(this, 1000);
}
}
};
handler.postDelayed(runable, 1000);
The handler is created in UI thread. Will such an infinite loop block the thread ? If not why not ?
There is no loop and control returns to the UI thread looper that processes the message queue. It won't block the UI thread.
However, you're congesting the UI thread in other ways. Each invocation of the runnable re-posts itself twice: once in try and second time in finally, therefore effectively doubling the number of events in the message queue each second. Eventually the UI thread won't be able to do any useful work processing other events.
Related
I use the code below for getting some work done everytime after some time interval, and using post delay in 'finally' clause and oustide of runnable. Here is the code.
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
// do somthing
} catch (Exception e) {
// TODO: handle exception
} finally {
handler.postDelayed(this, 60000);
}
}
};
handler.postDelayed(runnable, 60000);
handler.postDelayed(runnable, 60000); will run two times or a single time.
it depends!
first matter
how the each try / catch / finally block completes normally or abruptly?
the finally block "always ^" executes when the try block exits
This ensures that the finally block is executed even if an unexpected exception occurs.
^ exception from above - finally may not be executed if jvm exits or thread gets killed
for details see java specs:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.2
second matter
how Handler post/postDelayed method executes will pass? or fails? for some reason - for second this may happen if message was not placed in to the message queue - on failure, usually because the looper processing the message queue is exiting.
but most likely your statement will make a INFINITE loop
** ps. you need to throw an exception in try block or remove catch block (as try{} finally{} ) can exist "without" catch but code in catch block without rising any exception will make a compiler complain (code will not compile)
if you want loop n-times+1 you need to add some condition before postDelayed in Runnable run() method
in your case code flow execution:
postDelayed method from last line outside definition of runnable
execution of runnable by:
start of try block
with or without passing catch
through finally block with postDelayed in runnable run() method - wich will place runnable in message que for delayed execution on main thread
then infinite loop on 2
so should i remove last postDelay out side of run() method to achieve postDelay run only ones in one loop. – AndroidMob
you can write this in such way:
final Handler handler = new Handler();
handler.post(new Runnable() {
// this int will also be passed to method post delayed
// as "this" keyword applies to Anonymous Class
// which body contains everything between brackets of new Runnable() { ... }
int withThis = 1;
#Override
public void run() {
handler.postDelayed(this,1000);
}
});
so where should i call method to get done somthing ? in run() method..? – AndroidMob
this also depends what you want to achieve:
example
handler.post(new Runnable() {
int counter = 0;
#Override
public void run() {
boolean wasPlacedInQue = false;
doPreMethod();
if(counter =< 10) {
doMethod();
wasPlacedInQue = handler.postDelayed(this,1000);
}
if(wasPlacedInQue) {
counter++;
doPostyMethod();
} else doFailureMethod();
}
the code in run() method is executed synchronously on so called UI Thread - i'ts main thread which executes your application see:
https://developer.android.com/training/multiple-threads/communicate-ui.html
if you are interested to study it more I have made a full working example for you:
https://gist.github.com/c3ph3us/7d237d540e60597369856cb1fa652a23
it surely will run two times. Because they are two different messages and handler will handle them separately.
I've got this code to schedule a task every so often:
final Handler handler = new Handler();
Runnable update = new Runnable() {
#Override
public void run() {
try{
runOnUiThread(new Runnable(){
public void run(){
lbl.setText(info);
cpb.setProgress(Float.valueOf(textInfo);
}
});
handler.postDelayed(this, 1000);
}
catch (Exception e) {
// TODO: handle exception
}
}
};
I want to constantly update the UI (every second, etc). The code works, however, the interface starts lagging. After the code iterates the task a few times the interface stops responding.
Is there any way I can schedule a task to repeat periodically without overloading the memory and without the interface lagging.
Assuming lbl is a TextView and cpb is a ProgressBar, your code will not considerably lag any device as it is. The problem lies somewhere else. Also, you appear to have missed a closing bracket on (Float.valueOf(textInfo);.
As an aside, you are unnecessarily using runOnUiThread inside the Runnable from what I can see. When you create a new Handler() it is implicitly linked to the calling thread's Looper, which I am assuming is the UI thread. In which case, the update Runnable will already be running on the UI thread. EDIT: This should not be the cause of the lag for the record, since iirc runOnUiThread checks if it is being executed on the UI thread then just runs it immediately, without doing another post.
I have a thread.sleep and a handler postDelayed in my code:
handler.postDelayed(new Runnable() {
#Override
public void run() {
Log.e(TAG, "I ran");
mIsDisconnect = false;
}
}, DISCONNECT_DELAY);
After the handler code and after the user press the button I have this:
while (mIsDisconnect) {
try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {
Log.e(TAG, "problem sleeping");
}
}
If the user wait long enough I can get the "I ran" in my log. But if the user press the button before the delay is up, it seems that the postDelayed never gets a chance to execute. My question is, does the thread.sleep() mess with the handler postDelayed?
Edit: The purpose of this code is that I want to continue the program only after DISCONNECT_DELAY seconds has already passed. So if the user clicks to early, I have to wait for the elapsed time to finish.
I'm assuming your handler is associated with the same thread the other loop is running on. (A Handler is associated with the thread it is created in.)
postDelayed() puts the Runnable in the handler thread's message queue. The message queue is processed when control returns to the thread's Looper.
Thread.sleep() simply blocks the thread. The control does not return to the Looper and messages cannot be processed. Sleeping in the UI thread is almost always wrong.
To accomplish what you're trying to do, remove the sleep and simply use postDelayed() to post a Runnable that changes your app state (like you already do by setting a member variable mIsDisconnect). Then in the onClick() just check the app state (mIsDisconnect flag) whether it is ok to proceed or not.
I guess that the second section runs on the main thread and you didn't move between threads.
You can't put the main thread on sleep, you stop all UI issues and other stuff that should be run on this thread (the main thread).
Use postDelayed of the handler instead.
The best way is with a sentinel:
runnable = new Runnable() {
#Override
public void run() {
// condition to pass (sentinel == 1)
if (isActive == 0) {
handler.postDelayed(this, 1000); // 1 seconds
}
else {
// isActive == 1, we pass!
// Do something aweseome here!
}
}
};
handler = new Handler();
handler.postDelayed(runnable, 100);
I have a thread which handles my game loop, when i call .join() on this thread the application stops responding.
I've been trying to fix a problem where the programs never get to the code, I.E the thread never ends.
System.out.println("YAY");
My Thread for the Game Loop:
This thread successfully prints out "Game Ended" but never seems to finish.
Runnable startGameLoop = new Runnable() {//game loop
#Override
public void run() {
AiFactory ai = new AiFactory();
final Button play = (Button) findViewById(R.id.Play);
final Button pass = (Button) findViewById(R.id.Pass);
while(finish==false){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
currentPlayer = game.getPlayer();
if(currentPlayer.isPlayer()==false){
//System.out.println("passCount:" +game.getPasscount());
ai.decide(nextPlay, game.getPreviousPlayed(), currentPlayer, game.getPasscount() );
if(nextPlay.size()!=0){
runOnUiThread(new Runnable(){
public void run(){
changeArrow();
if(nextPlay.size() ==1){
play1Card();
}
else if(nextPlay.size()==2){
play2Card();
}
else if(nextPlay.size()==3){
play3Card();
}
else if(nextPlay.size()==5){
play5Card();
}
}
}
else{
game.addPassCount();
game.nextTurn();
runOnUiThread(new Runnable(){
public void run(){
changeArrow();
}
});
}
}
else if (currentPlayer.isPlayer()==true){
runOnUiThread(new Runnable(){
public void run(){
changeArrow();
play.setClickable(true);
if(game.getPasscount()==3){
pass.setClickable(false);
}
else{
pass.setClickable(true);
}
}
});
}
}
System.out.println("Game Ended");
}
};
Starting and joining the thread to the main thread:
Thread myThread = new Thread(startGameLoop);
myThread.start();
try {
myThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("YAY");
}
To my understanding .join() makes the current thread wait till the new thread has finished before carrying on.
Sorry if this is a stupid question, i'm quite new to threading.
When you call myThread.join() inside Activity.onCreate you block the main UI thread. Of course it looks like your application has stopped responding because the UI thread is the one responsible for redrawing UI. All your calls runOnUiThread never happen because your UI thread is busy waiting on your game loop.
Thread.join makes the current thread wait until the thread you call it on ends. It does not cause the thread you call it on to end. So if that thread is never ending (as you say at the top), calling join will make it hang forever.
If you want to actually end the thread, call cancel on it. But that requires your thread to occasionally call isCanceled() and exit its run function if it returns true.
mythread.join() does not ensure that your "mythread" is ended.
You need to place a notify() in your game loop.
...
...
System.out.println("Game Ended");
synchronized(mythread){
mythread.notify();
}
Basically, when you make a call to wait(), the code waits on the thread's monitor, and a call to notify() causes a thread waiting on the object's monitor to wake up.
Also, you can use notifyAll() to wake up all the waiting threads.
Alternatively, you can use timeout version of wait(), where the thread waits either till it gets notified or it times out.
I'm trying to run a piece of code periodically every 3 seconds that can change the color of a button.
So far I have:
ScheduledExecutorService scheduleTaskExecutor = Executors.newScheduledThreadPool(2);
// This schedule a runnable task every 2 minutes
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
public void run() {
queryFeedback2(); // display the data
}
}, 0, 3, TimeUnit.SECONDS);
This code will run the piece of code but will not update my UI with the results.
Firstly, what code be cause my UI updating issues?
And secondly, is this the way I should be running my code periodically? Is there a better way?
Yes, there are few options available.
Thread
Runnable
TimerTask
As stated by alex2k8 in their answer here:
final Runnable r = new Runnable()
{
public void run()
{
tv.append("Hello World");
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 1000);
Or we can use normal thread for example (with original Runner):
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1000);
handler.post(r);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
You may consider your runnable object just as a command that can be
sent to the message queue for execution, and handler as just a helper
object used to send that command.
More details are here
http://developer.android.com/reference/android/os/Handler.html
You can update the UI from
handler. Tutorial for using handler, thread is available here.
Selecting between above mentioned option is really based on what kind of functionality you need. If you only need to do something at few interval then any of the above should be fine.