CountDownTimer keeps repeating loop - java

I have a timer:
new CountDownTimer(10000, 1000) {
public void onTick(long millisUntilFinished)
{label.setText("Seconds Remaining: " + millisUntilFinished / 1000);}
public void onFinish() {doSomething();}
}.start();
It counts down from 10, and if it reaches 0 method 'doSomething()' is run. But it keeps repeating itself. I need 'doSomething()' to run only 10 times overall. Baring in mind that if the timer does not reach 0 another method needs to also run.
thanks, for any help

Yes it is good to know what doSomething() does. Moreover you may obtain the 10x execution using the onTick instead of onFinish. It really depends on what do you want to achieve. For example if doSomething is not reentrant using onTick would be not enough.

Related

Timer ending too early?

friends, I have this simple timer, which is suppose to tick every 10ms for the period of 2seconds.
breathTimer = new CountDownTimer(2000, 10) {
int currStep = 0;
public void onTick(long millisUntilFinished) {
Log.e(String.valueOf(currStep*10),String.valueOf(mSecPerBreath));
currStep++;
}
public void onFinish() {
Log.e("END: "+String.valueOf(currStep*10),String.valueOf(mSecPerBreath));
}
};
breathTimer.start();
Yet it always stops too early, for example
E/END: 1640: 2000
what do you think might be the problem?
or if I set the timer to 3000, it will end in E/END: 2520: 2000
As per documentation, seems like the onTick execution time is significant compared to the countdown interval (10ms). This could be the reason for the increased period (i.e. 2520).
The calls to onTick(long) are synchronized to this object so that one call to onTick(long) won't ever occur before the previous callback is complete. This is only relevant when the implementation of onTick(long) takes an amount of time to execute that is significant compared to the countdown interval.

how to run a code 60 times per second in java

if I don't control the number of times per second my code executes, when I add a line, the program varies and I have to adjust the constants again. (translated by Google)
My code running out of control:
public builder(){
while(true)
stepEvent();
}
private void stepEvent() {
setOfActions();
repaint();
}
This is just one way to do it(it's very long but VERY precise - I recommend it for game development). In this case I'm using the run() method from the Runnable interface to execute the code.
public void run(){
long lastTime = System.nanoTime();
final double ns = 1000000000.0 / 60.0;
double delta = 0;
while(true){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while(delta >= 1){
the code you want to be executed
delta--;
}
}
}
Explanation Line by Line:
Basically, I store the current time in nanoseconds in lastTime. Then in ns I store 1/60th of a second in nanoseconds and create a variable delta.
After this, I go inside the infinite while loop(it doesn't have to be infinite) and store the current time in nanoseconds once again in now. This is to take into account the amount of time that took the computer to go from the lastTime declaration line to the while loop line.
After doing all this, I add to delta the difference of now and lastTime divided by the 1/60th of a second(ns) I mentioned. This means that every time delta is equal to 1, 1/60th of a second will have passed.
Right after this, I make lastTime be the same as now. In the while loop that comes afterwards I check if delta is equal or greater than 1 and then in there you should put all the code you want to be executed 60 times per second. Don't forget to substract 1 from delta so it doesn't loop endlessly.
Analyze the code thoroughly and see if you can understand it. If you can't, I'll clarify further. I insist that this is just one possible way to do it, but there are many more ways.
Note: In some cases, you will never even need delta, but it is very helpful for some purposes.
Credit for the code: Most of this code(at least where I got it & learned it) is extracted from TheCherno's Game Programming Series
Have a great day!
import java.util.Timer;
import java.util.TimerTask;
public class HelloWorld {
public static void main(String []args) {
// number of ms in 1/60 of a second
// there will be some rounding error here,
// not sure if that's acceptable for your use case
int ms = 1000 / 60;
Timer timer = new Timer();
timer.schedule(new SayHello(), 0, ms);
}
}
class SayHello extends TimerTask {
public void run() {
System.out.println("Hello World!");
}
}
Basically, you have to execute your stepEvent every 17 ms.
With the assumption you want to run sequentially, you could stop the execution during a defined period by using Thread.sleep(millis , nanos). In this case, we will stop the thread 17ms minus the stepEvent execution time (think to add condition to avoid negative value in sleep function)
long startedTime;
for(;;){
startedTime = System.currentTimeMillis();
stepEvent();
Thread.sleep(17 - System.currentTimeMillis() + startedTime);
}
Otherwise you can use the ScheduledExecutorService which allows you to schedule code to run periodically at fixed time intervals (or after a specified delay). In this case, you can execute your step at a fixed rate every 17ms.
ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleAtFixedRate(YourClass::stepEvent, 0, 17, TimeUnit.MILLISECONDS);
You can also configure to use severals thread with Executors.newScheduledThreadPool

Handler.postDelayed function doesn't create time delays ? - Android

Below I have a Runnable "updater" ...and an OnClick function that uses Handler.PostDelayed function to run the runnable after a delay...
After a little editing, cutting of useless parts here are the functions:
(passtog = Toggle Button)
final Runnable updater = new Runnable() {
#Override
public void run() {
if (passTog.isChecked()) {
now = System.currentTimeMillis();
time = now - init;
if (time > 5000) {
Toast.makeText(getApplicationContext(), "WAKE UP !",
Toast.LENGTH_SHORT).show();
}
handler.postDelayed(this, 25);
}
}
};
passTog.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
init = System.currentTimeMillis();
flag = true;
handler.postDelayed(updater,
(new Random().nextInt(4000) + 3000));
}
});
}
Explaination
Basically, The user toggles the Toggle button. Now it's on: The runnable can run completely (Everything is in the if block).
If the user doesn't press the button again, and switches it off The app sends a Toast "Wake Up!" ..It runs and checks every 25 millisecs to update the time...
Pretty straightforward... Yet I'm having a problem.
Before the program actually gets to the runnable, I absolutely NEED there to be a minimum time delay of 3 seconds + Some Random value ... So it varies between 3 sec - 7 sec. It SHOULD vary between 3-7 , but it doesn't.
When I run it: The problem
I notice that the first time, it works great... I get atleast a 3 sec delay + a random value= Perfect
The second time, that is after the switch goes on ->off-> on : Now It acts like it doesn't see the +3000 ...and just the ~randInt(4000) function... So it may give 0 sec or it may give 4 sec delay...
In all my experience, I've never really come across this.. I've rewritten the entire code, My other apps use this function in exactly the same sytax and seem to do pretty great.. Why is this creating a problem ? Could the Toast's time possibly be causing a problem..
How to solve this ?
(I'm open to other methods, preferably quick to implement. I want a minimum 3 sec delay which I'm not getting for some reason... I need the UI to be responsive though So no thread sleeping.)
You probably should call Handler.removeCallbacksAndMessages(null) when the switch goes off.

Java - Android Programming - Loop Fail [duplicate]

I am using a while loop with a timer.
The thing is that the timer is not used in every loop.
It is used only the first time. After the first time the statements included inside the loop are executed without the delay that i have set.
How is this even possible since the timer is included inside the while loop.
Any solutions ?
int count = 1;
while (count <= 10) {
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
// Stuff the while loop executes
}
});
}
}, 20000);
count++;
}
The TimerTask kicks off a new Thread and then the loop proceeds as normal.
The execution of the thread does not cause a delay to the execution of the code in your loop.
It's because you're queueing up 10 toasts all to execute in one hour. Each iteration of your loop takes only a fraction of a millisecond or maybe a tad bit more than that. To enqueue them properly, you could do 3600000 * count instead of 3600000 each time.
This is a terrible way to do it though. You should use AlarmManager for stuff like this.
You're scheduling 10 TimerTasks to execute after an hour, at the same time. So all 10 tasks are being executed after 1 hour, which makes it seem like 1 execute since all the Toast messages display at the same time. To schedule tasks at a fixed delay, with the first task starting in 1 hour, use this method:
Timer t = new Timer();
t.schedule(task, 3600000, 3600000);
This will execute until you call t.cancel().

Java / Android Programming - Loop FAIL

I am using a while loop with a timer.
The thing is that the timer is not used in every loop.
It is used only the first time. After the first time the statements included inside the loop are executed without the delay that i have set.
How is this even possible since the timer is included inside the while loop.
Any solutions ?
int count = 1;
while (count <= 10) {
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
// Stuff the while loop executes
}
});
}
}, 20000);
count++;
}
The TimerTask kicks off a new Thread and then the loop proceeds as normal.
The execution of the thread does not cause a delay to the execution of the code in your loop.
It's because you're queueing up 10 toasts all to execute in one hour. Each iteration of your loop takes only a fraction of a millisecond or maybe a tad bit more than that. To enqueue them properly, you could do 3600000 * count instead of 3600000 each time.
This is a terrible way to do it though. You should use AlarmManager for stuff like this.
You're scheduling 10 TimerTasks to execute after an hour, at the same time. So all 10 tasks are being executed after 1 hour, which makes it seem like 1 execute since all the Toast messages display at the same time. To schedule tasks at a fixed delay, with the first task starting in 1 hour, use this method:
Timer t = new Timer();
t.schedule(task, 3600000, 3600000);
This will execute until you call t.cancel().

Categories