Reputation: 811
I am trying to develop a custom stop watch application in android but it throw following exception:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
I have also tried to use chronometer but when we use it's stop method it starts from its previous value.
following is my activity file
public class MainActivity extends Activity implements OnClickListener
{
TextView sec,milisec,min;
Button start,stop,pause,resume;
int count=0;
Chronometer chrono;
Timer timer;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
chrono=(Chronometer)findViewById(R.id.chronometer);
milisec=(TextView)findViewById(R.id.milisec);
sec=(TextView)findViewById(R.id.sec);
min=(TextView)findViewById(R.id.min);
start=(Button)findViewById(R.id.start);
stop=(Button)findViewById(R.id.stop);
pause=(Button)findViewById(R.id.pause);
resume=(Button)findViewById(R.id.resume);
System.out.println("-------1-------");
start.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
//chrono.start();
//count=Integer.parseInt(count_view.getText().toString());*/
timer = new Timer();
timer.schedule(new TimerTask()
{
public void run()
{
System.out.println("-------2-------");
View v = new View(getApplicationContext());
count_increment(v);
}
},1000,10000);
}
});
stop.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
//chrono.clearComposingText();
//chrono.setText("00");
timer.cancel();
}
});
}
public void count_increment(View v)
{
count++;
System.out.println("count="+count);
//count_str=String.valueOf(count);
milisec.setText(""+count);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
}
and following is xml file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginTop="30dp"
android:gravity="center_horizontal" >
<TextView
android:id="@+id/min"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":" />
<TextView
android:id="@+id/sec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":" />
<TextView
android:id="@+id/milisec"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00" />
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginTop="60dp"
android:gravity="center_horizontal" >
<TableLayout
android:layout_width="wrap_content"
android:layout_height="match_parent" >
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<Button
android:id="@+id/start"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:text="Start" />
<Button
android:id="@+id/stop"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:text="Stop" />
<Button
android:id="@+id/pause"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:text="Pause" />
<Button
android:id="@+id/resume"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:text="Resume" />
</TableRow>
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<Chronometer
android:id="@+id/chronometer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Chronometer" />
</TableRow>
</TableLayout>
</LinearLayout>
</RelativeLayout>
What is going wrong?
Is there any other way than this to develop stopwatch?
Upvotes: 4
Views: 799
Reputation: 4256
you cannot modify a view/setText from a child thread. A view can only be accessed from within the UI thread/main Thread.
try this from inside the child thread
runOnUiThread(new Runnable() {
@Override
public void run() {
count_increment(v);
}
});
Upvotes: 1
Reputation: 1969
The error message is quite self-explained: you shall not touch the UI element directly in a new thread. A possible workaround is that you post a runnable to the UI thread to update the UI by Activity.runOnUiThread()
I mean something like this (pseudo code not tested):
public void count_increment(View v)
{
count++;
System.out.println("count="+count);
//count_str=String.valueOf(count);
// milisec.setText(""+count);
final String str = ""+count;
runOnUiThread(new Runnable() {
public void run() {
milisec.setText(str);
}
});
}
Upvotes: 1