Reputation: 16978
I'm using a timer to create a stop watch. The timer works by increasing a integer value. I want to then display this value in the activity by constantly updating a textview.
Here's my code from the service where I try and update the activity's textview:
protected static void startTimer() {
isTimerRunning = true;
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
elapsedTime += 1; //increase every sec
StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
}
}, 0, 1000);
}
I got some kind of error about updating the UI in the wrong thread.
How can I adapt my code to accomplish this task of constantly updating the textview?
Upvotes: 52
Views: 74465
Reputation: 4641
I use this way:
String[] array = {"man", "for", "think"};
int j;
Then add more onCreate
:
TextView t = findViewById(R.id.textView);
new CountDownTimer(5000,1000) {
@Override
public void onTick(long millisUntilFinished) {}
@Override
public void onFinish() {
t.setText("I " + array[j] + " You");
j++;
if (j == array.length - 1) j = 0;
start();
}
}.start();
Upvotes: -1
Reputation: 1954
you can use Handler.
this code increase a counter every one second and show and update counter value on a textView.
public class MainActivity extends Activity {
private Handler handler = new Handler();
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.text);
startTimer();
}
int i = 0;
Runnable runnable = new Runnable() {
@Override
public void run() {
i++;
textView.setText("counter:" + i);
startTimer();
}
};
public void startTimer() {
handler.postDelayed(runnable, 1000);
}
public void cancelTimer() {
handler.removeCallbacks(runnable);
}
@Override
protected void onStop() {
super.onStop();
handler.removeCallbacks(runnable);
}
}
Upvotes: 2
Reputation: 5760
protected static void startTimer() {
isTimerRunning = true;
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
elapsedTime += 1; //increase every sec
mHandler.obtainMessage(1).sendToTarget();
}
}, 0, 1000);
}
public Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
StopWatch.time.setText(formatIntoHHMMSS(elapsedTime)); //this is the textview
}
};
Above code will work...
Note: Handlers must be created in your main thread so that you can modify UI content.
Upvotes: 92
Reputation: 83
timer.schedule(new TimerTask() {
@Override
public void run() {
//your actions
}
},1*1000);//1 sec
Upvotes: -3
Reputation: 8580
You can use the following utility :
/**
* Created by Ofek on 19/08/2015.
*/
public class TaskScheduler extends Handler {
private ArrayMap<Runnable,Runnable> tasks = new ArrayMap<>();
public void scheduleAtFixedRate(final Runnable task,long delay,final long period) {
Runnable runnable = new Runnable() {
@Override
public void run() {
task.run();
postDelayed(this, period);
}
};
tasks.put(task, runnable);
postDelayed(runnable, delay);
}
public void scheduleAtFixedRate(final Runnable task,final long period) {
Runnable runnable = new Runnable() {
@Override
public void run() {
task.run();
postDelayed(this, period);
}
};
tasks.put(task, runnable);
runnable.run();
}
public void stop(Runnable task) {
Runnable removed = tasks.remove(task);
if (removed!=null) removeCallbacks(removed);
}
}
Then anywhere in code that runs by the UI Thread you can use it simply like this:
TaskScheduler timer = new TaskScheduler();
timer.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
time.setText(simpleDateFormat.format(GamePlay.instance().getLevelTime()));
}
},1000);
Upvotes: 2
Reputation: 1557
StopWatch.time.post(new Runnable() {
StopWatch.time.setText(formatIntoHHMMSS(elapsedTime));
});
this code block is based on Handler but you don't need to create your own Handler instance.
Upvotes: 6
Reputation: 74780
You should use Handler
instead to update UI every X seconds. Here is another question that show an example: Repeat a task with a time delay?
Your approach doesn't work because you are trying to update UI from non-UI thread. This is not allowed.
Upvotes: 8
Reputation: 22240
I'm assuming StopWatch.time
is some static or public reference to your TextView. Instead of doing this, you should implement a BroadcastReceiver to communicate between your timer (which runs from a separate thread) and your TextView.
Upvotes: 2
Reputation: 3282
TimerTask implements Runnable, which would make it a thread. You can not update the main UI thread directly from a different thread without some work. One thing you could do is use Async Task to create the timer and publish an update every second that will update the UI.
Upvotes: 2