How to Stop Recursive Call Of Handler? - java

I created a handler, to imitate timer task.
because TimerTask was acting differently on different tablets.
so I created this handler method.
in timer there was a method timerTask.cancel();
but how to stop this handler
it keeps on running even after the application is exited.
as you can see logs running even after back press.
Handler handler = new Handler();
public void recursivelycallHandler(){
handler.postDelayed(new Runnable() {
#Override
public void run() {
Log.d("handler is running", "true" + System.currentTimeMillis());
recursivelycallHandler();
}
}, 100);
}

There are 3 methods to do that ..
handler.removeCallbacks(Runnable r);
handler.removeCallbacksAndMessages(null);
handler.removeMessages(int what)
In your case first two seem feasible .. add any of the above method in ondestroy or on a listener to backpress..

By putting any condition
Handler handler = new Handler();
int i = 0;
Runnable myRunnable = new Runnable() {
#Override
public void run() {
Log.d("handler is running", "true" + System.currentTimeMillis());
if(i>5)
handler.removeCallback(myRunnable);
else{
i++;
handler.postDelayed(myRunnable, 100); // here is self calling
}
}
};
}
handler.postDelayed(myRunnable, 100);
Its recursive method but you can call the same Runnable object in run() instead of recursive method and remove that object when based on specific situation/condition

You can store flag (boolean var) to detect if you need to call for your handler and before exit app change this flag to false and stop calling handler.

you can do something like this below:
public void recursivelycallHandler(){
handler.postDelayed(new Runnable() {
#Override
public void run() {
Log.d("handler is running", "true" + System.currentTimeMillis());
if(YOUR_CONDITION){
recursivelycallHandler();
}
}
}, 100);
}
Hope you got my point.
feel free to comment.

just add isFinished to your run method:
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (isFinished())
return;
Log.d("handler is running", "true" + System.currentTimeMillis());
recursivelycallHandler();
}
}, 100);

Related

Infinite-while or for loop after ActionEvent not working in swing. why?

public void myMethod()
{
if (capture.isOpened()) {
while (true) { //This is The main issue.
capture.read(webcam_image);
if (!webcam_image.empty()) {
webcam_image = my_panel.detect(webcam_image);
temp = my_panel.matToBufferedImage(webcam_image);
my_panel.setimage(temp);
my_panel.repaint();
System.out.print("."); // It should prints "." but the above code doesn't works.
} else {
System.out.println(" --(!) No captured frame -- Break!");
break;
}
}
}
}
This is invoking code of the above method...
actually it's an ActionEvent which can be fire on menu is clicked.
if (e.getActionCommand().equals("goLive")) {
System.out.println("Live...");
myMethod();
}
I know actually it's problem of the infinite while loop but here I need to put this condition at any cost.
The exact solution for this type of problem is Timer class. We can overcome this issue using the following code.
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
myMethod();
}
}, 0);
Thanks google, oracle and java doc
Assuming that myMethod is called by an event listener (actionPerformed), the infinite loop is blocking the event dispatch thread.
You can avoid this by using SwingWorker or executing your loop on another thread:
public void myMethod()
{
if (capture.isOpened()) {
new Thread(new Runnable() { //Create a new thread and pass a Runnable with your while loop to it
#Override public void run() {
while (true) {
capture.read(webcam_image);
if (!webcam_image.empty()) {
webcam_image = my_panel.detect(webcam_image);
temp = my_panel.matToBufferedImage(webcam_image);
SwingUtilities.invokeLater(new Runnable() { //The following lines affect the GUI and must be executed on the event dispatch thread, so they should be wrapped inside a Runnable
#Override public void run() {
my_panel.setimage(temp);
my_panel.repaint();
}
}
try{
Thread.sleep(xxx); //consider waiting for a moment (e.g. 16ms)
} catch(InterruptedException e) { ... }
System.out.print(".");
} else {
System.out.println(" --(!) No captured frame -- Break!");
break;
}
}
}
}).start(); //Let the thread loop in the background
}
}

Call method after delay

I've crated Log in screen, and if user mistake 3 times i want to show timer of 2 min. I want that timer to be visually shown on the screen. I'll try this code and it's work, but I don't know how to display timer on screen.
Handler handler = new Handler();
long waitingTime = 2 * 60 * 1000; // 2 min
handler.postDelayed(new Runnable() {
#Override
public void run()
{
//Do something after 2 min
}
}, waitingTime);
You need to have Handler called every second and update the UI during every pass. When you reach 2 mins you can cancel the handler.
Code should be like this:
final Handler handler = new Handler();
//class variable
count = 0;
handler.post(new Runnable() {
#Override
public void run() {
updateCounter(count++);
if(count < 120) {
handler.postDelayed(this, 1000);
}
}
});
And function to update counter:
private void updateCounter(final int count) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// you have the seconds passed
// do what ever you want
}
});
}
you need use runOnUiThread(Runnable action)

Execute method every second

I want to execude some code every second in android, but I'd like to do is in one thread (main thread). So far I have this:
locationTimer = new Timer("locationTimer", false);
locationTimer.schedule(new LocationCheckerTask(this), 0, 1000);
public class LocationCheckerTask extends TimerTask {
private GeoWatcher watcher;
public LocationCheckerTask(Context context) {
watcher = new GeoWatcher(context);
}
#Override
public void run() {
// funky stuff
}
}
Unfortunately, Timer class runs it's tasks on another thread.
Why I want to do this in a single thread?
Code in run() method will be executing really fast, so I figured I don't need another thread for it. What I want to do is to construct separate threads in run() method based on condition calculated every second. So instead of having child thread constructing another threads, I'd like to do this on the main one.
You can do this with Handler
public class Job implements Runnable{
private Handler handler;
public Job () {
handler = new Handler(Looper.getMainLooper());
loop();
}
#Override
public void run() {
// funky stuff
loop();
}
private void loop() {
handler.postDelayed(this, 1000);
}
}
use runOnUiThread(Runnable) method of Activity to run the task in UI Thread
public class LocationCheckerTask extends TimerTask {
private GeoWatcher watcher;
public LocationCheckerTask(Context context) {
watcher = new GeoWatcher(context);
}
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
// funky stuff
}
});
}
}
the Handler is a perfect candidate for such tasks (dont try to combine TimerTask + runOnUiThread - it is useless as it uses a Handler under the hood)
private Runnable fiveSecondRunnable = new Runnable() {
#Override
public void run() {
if (count5 < 0) {
switchT030Sec();
} else {
tvSec5.setText(""+count5);
Log.v("5sec set", "yes");
count5--;
man.postDelayed(this, 1000);
}
}
};
and start it by calling
man.post(fiveSecondRunnable);

How to run a thread repeatedly after some interval

I want to run a thread (Which does some time consuming task in background and does NOT update UI) it just downloads some files form the internet and it is independent from the UI.
I want to run this thread repeatedly after some time interval.
How can i do this, I have thread something like below:
boolean mResult =false;
void onCreate()
{
DownloadThread mDownloadThread = new DownloadThread();
mDownloadThread.start();
}
class DownloadThread extends Thread implements Runnable
{
public void run()
{
// My download code
mResult = result;
}
}
Do i need to use Handler for implementing this?
Option 1:
volatile boolean flag = true;
public void run()
{
while(flag)
{
// Do your task
try{
Thread.Sleep(interval);
} catch(Exception e){
}
}
}
Option 2:
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Do your task
}
}, 0, interval);
Option 3:
volatile boolean flag = true;
public void someMethod(){
// Do your task
try{
Thread.Sleep(interval);
} catch(Exception e){
}
if(flag)
return;
else
someMethod();
}
Option 4:
final Handler handler = new Handler();
volatile boolean flag = true;
Class A implements Runnable{
public void run(){
// Do your Task
}
if(!flag)
handler.postDelayed(a, interval);
}
A a = new A();
handler.postDelayed(a);
There will be many more options. I never tried option 3 and 4. It just came to my mind and I wrote. If I were you I would use any of 1 or 2.
Prefered choice is
java.util.concurrent.ScheduledExecutorService
Newer and robust implementation, More here ScheduledExecutorService
I would use a Timer to achieve this. Try this:
void onCreate()
{
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Download your stuff
}
}, 0, 1000);
}
It starts immediately and the run-Method gets called every second.

Is this how to schedule a java method to run 1 second later?

In my method, I want to call another method that will run 1 second later. This is what I have.
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
MyMethod();
Log.w("General", "This has been called one second later");
timer.cancel();
}
}, 1000);
Is this how it's supposed to be done?
Are there other ways to do it since I'm on Android?
Can it be repeated without any problems?
There are several alternatives. But here is Android specific one.
If you thread is using Looper (and Normally all Activity's, BroadcastRecevier's and Service's methods onCreate, onReceive, onDestroy, etc. are called from such a thread), then you can use Handler. Here is an example:
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
myMethod();
}
}, 1000);
Note that you do not have to cancel anything here. This will be run only once on the same thread your Handler was created.
Instead of a Timer, I'd recommend using a ScheduledExecutorService
final ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
exec.schedule(new Runnable(){
#Override
public void run(){
MyMethod();
}
}, 1, TimeUnit.SECONDS);
If you are not in UI thread, consider adding a very simple:
try
{
Thread.sleep( 1000 );
}//try
catch( Exception ex)
{ ex.printStackTrace(); }//catch
//call your method
ScheduledExecutorService or AsyncTask for UI related.
Note that if you are to update UI, that code should be posted to UI thread. as in Processes and Threads Guide
final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
There is also nice postDelayed method in View
mImageView.postDelayed(new Runnable(){
#Override
public void run() {
mImageView.setImageResource(R.drawable.ic_inactive);
}
}, 1000);
that will update UI after 1 sec.

Categories

Resources