I have a class with a handler in it and it works fine, but it then hits a class where I want the handler to stop if the timer has not already timed out. So if the handler reaches the end it should go to the Drunk class, if the user reaches the end of the app before the handler goes off, the handler should not go off. I have it going off at the end of the app but I don't want it too. It should stop once it hits the end of the app.
THANKS!
Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run()
{
toDrunk();
}
},20000);
public void toDrunk(){
Intent i = new Intent(this, Drunk.class);
startActivity(i);
}
You need to remove that message from the handler when the activity is stopped. You can do that either by storing the runnable in some variable and then removing it using removeCallbacks or by posting the runnable with some token and then removing all messages with that token using removeCallbacksAndMessages.
Related
final Handler handler = new Handler();
LOG.d("delay");
handler.postDelayed(new Runnable() {
#Override public void run() {
LOG.d("notify!");
//calling some methods here
}
}, 2000);
The "delay" does shows in the log, but not others at all. And the method called in the run() is not called at all also. Can anyone help explain why this happens, am I doing anything wrong?
The class that has this code extends IntentService, will this be a problem?
============================
UPDATE:
I put this code in the class that extends IntentService. The only place I found it worked was in the constructor. But I need to put it in the onHandleIntent method. So I checked the documentation for onHandleIntent and it said:
This method is invoked on the worker thread with a request to process.Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call stopSelf.
So based on the result I get, I feel like I cannot use postDelayed in "worker thread". But can anyone explain this a bit more, like why this is not working in worker thread? Thanks in advance.
Convert
final Handler handler = new Handler();
to
final Handler handler = new Handler(Looper.getMainLooper());
This worked for me.
You are using looper of the main thread. You must create a new looper and then give it to your handler.
HandlerThread handlerThread = new HandlerThread("background-thread");
handlerThread.start();
final Handler handler = new Handler(handlerThread.getLooper());
handler.postDelayed(new Runnable() {
#Override public void run() {
LOG.d("notify!");
// call some methods here
// make sure to finish the thread to avoid leaking memory
handlerThread.quitSafely();
}
}, 2000);
Or you can use Thread.sleep(long millis).
try {
Thread.sleep(2000);
// call some methods here
} catch (InterruptedException e) {
e.printStackTrace();
}
If you want to stop a sleeping thread, use yourThread.interrupt();
this is how i use handler:
import android.os.Handler;
Handler handler;
//initialize handler
handler = new Handler();
//to start handler
handler.post(runnableName);
private Runnable runnableName= new Runnable() {
#Override
public void run() {
//call function, do something
handler.postDelayed(runnableName, delay);//this is the line that makes a runnable repeat itself
}
};
Handlers and Services will be predictable when the device screen is on.
If the devices goes to sleep for example the Handler will not be a viable solution.
A much more better and reliable solution will be to use:
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
IntentService is not designed for such scenario. You can use a regular Service instead. You can put the handler inside the onStartCommand(). Don't forget to
call stopSelf() on the Service instance to shut it down after the handler.postDelayed(){}
The most simple is to wait before ending onHandleIntent():
SystemClock.sleep(2000);
I am using following code to run a timer.
Handler handler = new Handler();
int time=0;
Runnable runable = new Runnable() {
#Override
public void run() {
time++;
Log.d("time", ""+time);
textview.setText(""+time);
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(runable, 1000);
This handler is attached to UI thread. When I navigate away to some other activity and come back to this activity I get two timers, the old one still persists, I can see this in logcat. Why this is happening ? How to get rid of old timers ?
The reason you have two timers, depends on where your code is in the activity. Activity.onStart and Activity.onResume can (not always) both get called when returning to an activity.
When Activity.onPause, or Activity.onStop is called you can call handler.removeCallbacks(Runnable) to remove your timer runnable.
In my app (as long as it is open) I want to sync my data with my server.
My strategy is the following :
//create the handler on which we will use postdelayed
Handler handler = new Handler();
//create the first runnable.
//Will this run on UI thread at this stage ? as it is being called from the handler ?
Runnable runnable1 = new Runnable()
{
public void run()
{
Thread t = new Thread(runnable2);
}
};
//create the second runnable.
//This is for sure being called from a thread, so it will not run on UI thread ? NO ?
Runnable runnable2 = new Runnable()
{
public void run()
{
//connect to internet
//make the check periodical
handler.postdelayed(runnable1, 1000);
}
};
//call the postdelayed.
handler.postdelayed(runnable1, 1000);
In case I want the handler to stop its runnable task once the application is closed. What shall I do incase I have several activities and I do not know where is the user when he/clicks the home button. Should I include a check in all onDestroys() ?
Yes you're second Runnable will be ran on a new thread not the UI thread.
When you do new Handler(); this creates a handle to the current thread, if this code was in onCreate that thread would be the UI thread.
Therefore when you do handler.post it will post onto the UI thread (runnable1) , but when you start runnable2 you are explicitly creating a new thread to run this on.
It might not be the right strategy to create a new thread every 1 second (postDelayed ..1000) perhaps keep a reference to another background thread and post it a message every second to do something new.
To stop your repeated runnables you need to call removeCallbacks(runnable1) in onPause of any Activity (that I assume called postDelayed in onCreate)
In my android application I created 2 handlers. One handler received message and waiting(calling wait();). At this point if I post messages to second Handler, it is not receiving. After some time I am getting dialog box saying Application not responding "Force Close" or "Wait buttons".
I think because of wait() in one handler, blocking second handler to receive messages.
Please suggest me solution to this problem.
You should create two threads and create a handler in each of these two threads and call Looper.loop in the run method of both the threads
class HandlerThread1 extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
Same way create HandlerThread2 and start both the threads.
You should never call wait in Ui thread, that is the reason you are getting App not responding popup. You can always post another message with duration instead of wait
I have written a handler that calls the method every time interval. I want to remove that handler in on destroy(). The code i use as follows, In Oncreate()
private final Handler _handler = new Handler();
public int DATA_INTERVAL = 30 * 1000;
Runnable getData;
getData = new Runnable()
{
#Override
public void run()
{
recieveData();
}
};
_handler.postDelayed(getData, DATA_INTERVAL);
and in ondestroy(), i use,
_handler.removeCallbacks(getData);
But removecallbacks not work. It calls after exiting the activity.
removeCallbacks(Runnable r):
Remove any pending posts of Runnable r that are in the message queue.
so removeCallbacks(..) only stops pending messages (Runnables) not currently running runnable so if you want to stop currently running Runable then use a Boolean varaible for Stoping Thread when user Exit from your app.
see this post for removeCallbacks not stopping runnable
You are not showing the most important part of the code which is the receiveData method. As you said you are running the task periodically, you must be calling again postDelayed from inside that method to reschedule the task. Probably background threads involved as you cannot do networking on the main thread.
You most likely have a race condition when exiting the Activity. onDestroy runs first and then the task is posted again.
You should use
handler.removeCallbacksAndMessages(null);
Then all handler callbacks will removed.