Reputation: 10095
Here's my code for a stopwatch application on Android:
package com.google.labyrinth;
public class Tabalicious extends Activity implements OnClickListener, Runnable
{
TextView stopwatchCounter;
long startTime, stopTime;
Thread stopwatch;
Button buttonStart;
Button buttonStop;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView( R.layout.tabalicious );
stopwatchCounter = (TextView) findViewById ( R.id.txtStopwatchCounter );
buttonStart = ( Button ) findViewById ( R.id.buttonStart );
buttonStop = ( Button ) findViewById ( R.id.buttonStop );
buttonStart.setOnClickListener( this );
buttonStop.setOnClickListener( this );
buttonStop.setEnabled(false);
}
public void onClick(View viewClicked)
{
switch( viewClicked.getId() )
{
case R.id.buttonStart:
this.buttonStart.setEnabled(false);
this.buttonStop.setEnabled(true);
this.startTime = System.currentTimeMillis();
stopwatch = new Thread(this);
stopwatch.start();
break;
case R.id.buttonStop:
this.buttonStop.setEnabled(false);
this.buttonStart.setEnabled(true);
try {
stopwatch.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
}
public void run()
{
//Update after 5 seconds.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.stopTime = System.currentTimeMillis();
this.stopwatchCounter.setText( String.valueOf( (this.stopTime - this.startTime) ) ); //<- Debugger Info: This line is at the top of the call stack.
}
}
The problem is that when I run the application I get a CalledFromWrongThread exception:
02-10 19:53:32.835: E/AndroidRuntime(18482): FATAL EXCEPTION: Thread-10 02-10 19:53:32.835: E/AndroidRuntime(18482):
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 02-10 19:53:32.835: E/AndroidRuntime(18482):
at android.view.ViewRoot.checkThread(ViewRoot.java:3092) 02-10 19:53:32.835: E/AndroidRuntime(18482):
at android.view.ViewRoot.invalidateChild(ViewRoot.java:677) 02-10 19:53:32.835: E/AndroidRuntime(18482):
at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:703) 02-10 19:53:32.835: E/AndroidRuntime(18482):
at android.view.ViewGroup.invalidateChild(ViewGroup.java:2597) 02-10 19:53:32.835: E/AndroidRuntime(18482):
at android.view.View.invalidate(View.java:5326) 02-10 19:53:32.835: E/AndroidRuntime(18482):
at android.widget.TextView.checkForRelayout(TextView.java:5761) 02-10 19:53:32.835: E/AndroidRuntime(18482):
at android.widget.TextView.setText(TextView.java:2814) 02-10 19:53:32.835: E/AndroidRuntime(18482):
at android.widget.TextView.setText(TextView.java:2682) 02-10 19:53:32.835: E/AndroidRuntime(18482):
at android.widget.TextView.setText(TextView.java:2657) 02-10 19:53:32.835: E/AndroidRuntime(18482): at com.google.labyrinth.Tabalicious.run(Tabalicious.java:144) 02-10 19:53:32.835: E/AndroidRuntime(18482): at java.lang.Thread.run(Thread.java:1027)
I'm not quite clear on what's going on. I would appreciate your help. thanks!
Upvotes: 0
Views: 423
Reputation: 1
this is only because you do :
this.stopwatchCounter.setText( String.valueOf( (this.stopTime - this.startTime) ) );
inside stopwatch thread, you can't touch the view because it isn't the UIThread.
Upvotes: 0
Reputation: 6366
You are trying to edit UI elements but you are not on the UI thread. In Android, UI elements can only be edited by the UI thread. There are many ways to update UI elements after doing computation on another thread, including calling the runOnUiThread() method, using a Handler, or overriding the PostExecute() method of an AsyncTask.
Upvotes: 2