I have a simple program with one TextView and two Buttons: Button1 and Button2.
Clicking on Button 1 will start a counter, increasing by 1 every 1 second and show result on TextView; clinking on Button 2 will stop it. Here is a part of my code for Button1. But it does not work.
Timer T=new Timer();
T.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
myTextView.setText("count="+count);
count++;
}
}, 1000, 1000);
I know that there are some similar questions about this using Thread but it seems like they do not mention about stopping the counter.
Any suggestion is really appreciated.
Added:
Hello, I just shortened my code just to this from a much bigger program, but it is still crashed:
package com.example.hello;
import java.util.Timer;
import java.util.TimerTask;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView myTextView;
int count=0;
Timer T;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myTextView=(TextView)findViewById(R.id.t);
T=new Timer();
T.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
myTextView.setText("count="+count);
count++;
}
}, 1000, 1000);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
The log file (I do not want to post this because it is too long but someone requested it):
07-28 17:35:07.012: W/dalvikvm(11331): threadid=7: thread exiting with uncaught exception (group=0x4001d800)
07-28 17:35:07.016: E/AndroidRuntime(11331): FATAL EXCEPTION: Timer-0
07-28 17:35:07.016: E/AndroidRuntime(11331): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
07-28 17:35:07.016: E/AndroidRuntime(11331): at android.view.ViewRoot.checkThread(ViewRoot.java:2802)
07-28 17:35:07.016: E/AndroidRuntime(11331): at android.view.ViewRoot.requestLayout(ViewRoot.java:594)
07-28 17:35:07.016: E/AndroidRuntime(11331): at android.view.View.requestLayout(View.java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331): at android.view.View.requestLayout(View.java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331): at android.view.View.requestLayout(View.java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331): at android.view.View.requestLayout(View.java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331): at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:254)
07-28 17:35:07.016: E/AndroidRuntime(11331): at android.view.View.requestLayout(View.java:8125)
07-28 17:35:07.016: E/AndroidRuntime(11331): at android.widget.TextView.checkForRelayout(TextView.java:5378)
07-28 17:35:07.016: E/AndroidRuntime(11331): at android.widget.TextView.setText(TextView.java:2688)
07-28 17:35:07.016: E/AndroidRuntime(11331): at android.widget.TextView.setText(TextView.java:2556)
07-28 17:35:07.016: E/AndroidRuntime(11331): at android.widget.TextView.setText(TextView.java:2531)
07-28 17:35:07.016: E/AndroidRuntime(11331): at com.example.hello.MainActivity$1.run(MainActivity.java:21)
07-28 17:35:07.016: E/AndroidRuntime(11331): at java.util.Timer$TimerImpl.run(Timer.java:289)
As @hovanessyan suggested: You can use the Chronometer class. E.g., as follows (with Kotlin, Java analog):
In the
my_layout.xml
:Chekout this example, that uses the Chronometer class: http://android-er.blogspot.com/2010/06/android-chronometer.html
Using the Chronometer class will save you managing the thread yourself.
You can introduce flag. Something like
isPaused
. Trigger this flag whenever 'Pause' button pressed. Check flag value in your timer task. Success.Pavel is on the right track with stopping it, except his answer is a waste since it doesn't stop the Timer. Do this on the part he posted with the added else statement:
Oh and you said it crashed. We have no idea why it's crashing, so unfortunately we cannot really help figuring out why its doing that unless we see more code and the error.
Good catch @yorkw The problem is obviously with something its trying to do when its starts running. Since its says "Timer-0", this means it never starts officially and it gets stuck in that part. First rule of running threads, NEVER CHANGE UI ELEMENTS FROM OUTSIDE THE UI. I would suggest using
runOnUiThread
like york said. Here's a link on how to use it: runOnUiThread. Pretty sureTimerTask
is a runnable meaning it runs on a separate thread. Least thats what I noticed on the docs.Perfect solution if you want to display running clock.
This way it is much simpler. It is a feature made available on the android developer site. Link