TimerTask not stopping after I click the stopbutton - java

So I click a start button and every second I change the text of a label with counting the time:
new CountDownTimer(30000, 500) {
public void onTick(long millisUntilFinished) {
if (zaciatokgotten) {
T2 = new Timer();
tt2 = new TimerTask() {
public void run() {
if(stopclicked == true) {
this.cancel();
}
handler.post(new Runnable() {
public void run() {
hasStartedtt2 = true;
calendar = Calendar.getInstance();
simpledate = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
do_casu = simpledate.format(calendar.getTime());
zaciatok_hour = zaciatok.substring(11, 13);
zaciatok_minute = zaciatok.substring(14, 16);
koniec_hour = do_casu.substring(11, 13);
koniec_minute = do_casu.substring(14, 16);
zaciatok_sekundy = zaciatok.substring(17, 19);
koniec_sekundy = do_casu.substring(17, 19);
final_hour = ((Integer.parseInt(koniec_hour) - Integer.parseInt(zaciatok_hour)) );
final_minute = Integer.parseInt(koniec_minute) - Integer.parseInt(zaciatok_minute);
final_seconds = Integer.parseInt(koniec_sekundy) - Integer.parseInt(zaciatok_sekundy) - 1;
if (final_seconds < 0) {
final_seconds = final_seconds + 60;
final_minute = final_minute - 1;
}
if (final_minute < 0) {
final_hour = final_hour - 1;
final_minute = final_minute + 60;
}
if (final_hour < 0) {
final_hour = 0;
}
if (final_minute < 0) {
final_minute = 0;
}
if (final_hour == 0) {
if (final_minute == 0) {
txtProgress.setText(final_seconds + " s");
} else {
txtProgress.setText(final_minute + " m " + final_seconds + " s");
}
} else {
txtProgress.setText(final_hour + " h " + final_minute + " m " + final_seconds + " s");
}
}
});
}
};
T2.schedule(tt2, 1000, 1000);
if(once ==0) {
new Thread(new Runnable() {
#Override
public void run() {
while (pStatus <= 100) {
handler.post(new Runnable() {
#Override
public void run() {
progressBar.setProgress(pStatus);
}
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
pStatus++;
if (pStatus == 100) {
pStatus = 0;
}
}
}
}).start();
once++;
this.cancel();
}
}}
public void onFinish() {
}
}.start();
After I click the stop button the progressBar stops spinning, which is correct, but the time keeps incrementing, what am I doing wrong? Note that this issue is not present on the phones I used to test it, but its present on tablet devices, maybe they handle threads differently?
The code for stopping the timer here:
stopclicked = true
if(hasStartedtt2 == true) {
tt2.cancel();
// handler.removeCallbacksAndMessages(null);
}
if (T2 != null) {
T2.cancel();
T2.purge();
}
pStatus = 101;
EDIT1: I just noticed it is stopped, but only 20 - 25 seconds after I clicked Stop, whats causing the delay?

The reason time won't stop (or stops "only 20 - 25 seconds after you clicked Stop") is the new instances of T2 = new Timer() and tt2 = new TimerTask() you create on every CountDownTimer's onTick(). The old instances of Timer and TimerTask keep residing on Java heap making their job until getting garbage-collected. You may notice the time changes being bumpy.
Moreover, you seem to overcomplicate the task implementation. You might not need neither Timer nor TimerTask. The following example, that stops the time going, uses only CountDownTimer without Timer and TimerTask. I simplified the code a bit for the sake of brevity.
private CountDownTimer timer;
private TextView txtProgress;
private Button stopButton;
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtProgress = findViewById(R.id.tv);
timer = new CountDownTimer(30000, 500) {
public void onTick(long millisUntilFinished) {
handler.post(() -> {
txtProgress.setText("any text");
});
}
public void onFinish() { }
}.start();
findViewById(R.id.stopButton).setOnClickListener(v -> timer.cancel());
}

Related

android studio - how to stop runnable?

please teach me how to stop my runnable.
"handler.removeCallback(sS)" does not work.
Or is my program wrong?
int life = 100, damage = 5;
public void gameOver()
{
((TextView)findViewById(R.id.textView6)).setVisibility(View.VISIBLE);
}
final Runnable sS = new Runnable()
{
#Override
public void run()
{
life = life - damage;
String lifeHP = String.valueOf(life);
((TextView)findViewById(R.id.textView)).setText(lifeHP);
handler.postDelayed(this, 300);
if (life < 0 )
{
gameOver();
//handler.removeCallback(ss)--does not work.
}
}
};
handler.post(sS);

Stop, close, end, thread in java based on condition

I am not sure how to get this working. I want one this tread to stop once (startNumber == 0 || !Player.cCounting). !Player.cCounting is a boolean that is accessed. If either condition is met I want the loop to stop.
public class Console {
static long lastTime;
static boolean cCounting = true;
static long seconds = 0;
static long delta = 0;
static int startNumber = (int) Level.cookieTime / 1000;
Thread countDown;
public Console() {
cookieCountDown();
lastTime = System.currentTimeMillis();
}
public void cookieCountDown() {
countDown = new Thread(new Runnable() {
#Override
public void run() {
startNumber = (int) Level.cookieTime / 1000;
while (startNumber != 0) {
cCounting = Game.enter;
//System.out.println(cCounting);
try {
Thread.sleep(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (startNumber > 0 && cCounting) {
long now = System.currentTimeMillis();
delta = now - lastTime;
if (delta >= 1000) {
delta = 0;
lastTime = System.currentTimeMillis();
System.out.println("cookie " + startNumber);// print countdown;
startNumber--;
System.out.println(Player.cCounting);
if (Player.cCounting = false) {
end();
}
}
}
}
}
});
countDown.start();
}
public void end() {
System.out.println(startNumber);
System.out.println(cCounting);
if (startNumber == 0 || !Player.cCounting) {
System.out.println("stop");
//countDown.interrupt();
//countDown.stop();
}
}
}
You just need to exit your loop. Replace your end(); method call with return;. and make startNumber and Player.cCounting volatile e.g. volatile static int startNumber

Class countdown timer doesn't reset

I have a class countdown timer that I want to reset but when it resets it wont start again.
Basicaly when the counter gets to 0 (when the status is "done"), sets x = 1 and then in the activity checks if x = 1 , and then the counter resets. When the reset method from within the class is called it shows that it has reset but it wont start counting again
Timer class:
public class countdown_timer {
private long pls;
private long millisInFuture;
private long countDownInterval;
private boolean status;
int x = 0;
public countdown_timer(long pMillisInFuture, long pCountDownInterval) {
this.millisInFuture = pMillisInFuture;
this.countDownInterval = pCountDownInterval;
this.pls = pMillisInFuture;
status = false;
Initialize();
}
public void Stop() {
status = false;
}
public int GetNumberX() {
return x;
}
public void Reset() {
millisInFuture = pls;
x=0;
}
public void Start() {
status = true;
}
public void Initialize() {
final Handler handler = new Handler();
Log.v("status", "starting");
final Runnable counter = new Runnable() {
public void run() {
long sec = millisInFuture / 1000;
if (status) {
if (millisInFuture <= 0) {
Log.v("status", "done");
x = 1;
} else {
Log.v("status", Long.toString(sec) + " seconds remain");
millisInFuture -= countDownInterval;
handler.postDelayed(this, countDownInterval);
}
} else {
Log.v("status", Long.toString(sec) + " seconds remain and timer has stopped!");
handler.postDelayed(this, countDownInterval);
}
}
};
handler.postDelayed(counter, countDownInterval);
}
Activity that uses the timer class:
mycounterup = new countdown_timer(startcard, 1000);
xup = mycounterup.GetNumberX();
if (xup == 1) {
mycounterup.Reset();
mycounterup.Start();
Thanks for any help.
try changing your start method as and one thing more i don't know if its a typo or what change mycounter.Start(); to mycounterup.Start();
public void Start() {
status = true;
Initialize();
}
save the counter state so that next time if you have to pause or resume the thing you are able to do it also
You should change your Reset method:
public void Reset() {
millisInFuture = pls;
x=0;
Initialize();
}

How to use Java.Util.Timer

I want to make a simple program that counts seconds up until 100 using Java.Util.Timer
The code below is the code I am using, however it simply prints all the numbers out at once without waiting a second between each one. How would I fix that? (Ordinarily I would use a thread.sleep but this is just proof of concept.)
import java.util.Timer;
import java.util.TimerTask;
public class Main {
static Timer timer = new Timer();
static int seconds = 0;
public static void main(String[] agrs) {
MyTimer();
}
public static void MyTimer() {
TimerTask task;
task = new TimerTask() {
#Override
public void run() {
while (seconds < 100) {
System.out.println("Seconds = " + seconds);
seconds++;
}
}
};
timer.schedule(task, 0, 1000);
}
}}
Don't use this while loop:
task = new TimerTask() {
#Override
public void run() {
while (seconds < 100) {
System.out.println("Seconds = " + seconds);
seconds++;
}
}
};
The while loop will run immediately as there's no delay inside of it. Instead you want to Timer itself to be your loop, meaning there's no need for this loop.
Instead use an if block to check if the count is < some max number and if so, print it out and increment the count.
task = new TimerTask() {
private final int MAX_SECONDS = 100;
#Override
public void run() {
if (seconds < MAX_SECONDS) {
System.out.println("Seconds = " + seconds);
seconds++;
} else {
// stop the timer
cancel();
}
}
};
In order to stop the timer the timer.cancel() should be invoked (not only the one of the TimerTask), so the timer is stopped and in cascade the other related threads.
#Override
public void run() {
if (seconds < Orologio.MAX_SECONDS) {
System.out.println("Seconds = " + seconds);
seconds++;
} else {
timer.cancel();
System.out.println("Timer canceled");
}
}
};

Android:About AndEngine updateThread and uiThread

I recently explore on AndEngine. I write a simple test demo, in which I implement IOnSceneTouchListener and the scene registers a TimerHandler to change one ChangableText.
And I set the engine runOnUpdateThread true.
So the problem is: when I touched the scene a while, the activity paused and crashed. And the Logcat showed the same text as before:"org.anddev.andengine.util.pool.PoolUpdateHandler$1 was exhausted, with 1 item not yet recycled. Allocated 1 more."
If anyone can solve my problem, so thankful I will be!
PS: my code
public class TestActivity extends BaseGameActivity implements IOnSceneTouchListener, IOnMenuItemClickListener {
...
...
private TimerHandler mTimeUpdateHandler = new TimerHandler(1.f, true, new ITimerCallback() {
#Override
public void onTimePassed(TimerHandler arg0) {
runOnUpdateThread(new Runnable() {
#Override
public void run() {
if (mElapsedText != null && mAttempts > 0) {
mElapsedText.setText("Time: "
+ (ParticlyActivity.this.mEngine.getSecondsElapsedTotal() - mCurrentTotalSeconds),
false);
}
}
});
}
});
...
...
// #Override
public Engine onLoadEngine() {
this.mCamera = new BoundCamera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
final EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE,
new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), mCamera).setNeedsSound(true);
engineOptions.getTouchOptions().setRunOnUpdateThread(true);
this.mEngine = new Engine(engineOptions);
return this.mEngine;
}
public Scene onLoadScene(){
...
// Text
mElapsedText = new ChangeableText(20, 12, this.mFont, "Time:00.00");
mScene.getFirstChild().attachChild(mElapsedText);
mScene.registerUpdateHandler(mTimeUpdateHandler);
...
}
#Override
public boolean onSceneTouchEvent(final Scene pScene, final TouchEvent pSceneTouchEvent) {
if ((pSceneTouchEvent.isActionMove() || pSceneTouchEvent.isActionDown()) && mAttempts < MaxBullets) {
double angle = 0;
if ((pSceneTouchEvent.getX() - StartX) == 0) {
angle = 90;
} else {
angle = Math
.abs(Math.atan((StartY - pSceneTouchEvent.getY()) / (StartX - pSceneTouchEvent.getX())) / 3.14 * 180);
}
if (angle > 90) {
angle = 90;
} else if (angle < 0) {
angle = 0;
}
mGun.setRotation((float) -angle);
mGun.setStrength(pSceneTouchEvent.getX());
} else if (pSceneTouchEvent.isActionUp() && mAttempts < MaxBullets) {
...
}
}
return true;
}
}
TimerHandler:
private TimerHandler mTimeUpdateHandler = new TimerHandler(1.f, true, new ITimerCallback() {
#Override
public void onTimePassed(TimerHandler arg0) {
runOnUpdateThread(new Runnable() {
#Override
public void run() {
if (mElapsedText != null && mAttempts > 0) {
mElapsedText.setText("Time: " + (ParticlyActivity.this.mEngine.getSecondsElapsedTotal() - mCurrentTotalSeconds), false);
}
}
});
}
});
UIThread is the one responsible for drawing , UpdateThread gets executed every frame
if you need to change Text values , do that on the UpdateThread [just stay away from the UIThread in general]

Categories