Updating a view from a separate thread

Recently I got the following exception in an android application, when I tried to update a view from a separate thread started in an activity.

03-15 21:39:35.799: E/AndroidRuntime(15580): 
android.view.ViewRootImpl$CalledFromWrongThreadException: 
Only the original thread that created a view hierarchy can touch its views.

The reason for this exception is that the view can not be updated from a thread other than the main thread that will be implicitly started and controlled by the system when the application is launched. This main thread is responsible for updating the UI. Actually this is a main element in the android framework (but also very common in other frameworks), as it enforces that updates to the UI will be done in a sequential manner within a single thread controlled by the system.

Assuming an activity which implements the Runnable interface, the following coding will always throw the mentioned exception, as the update of the view element, implemented in the run() method, is intended to be done in a separate thread, which is not allowed!

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity implements Runnable{
	
	private MyView theView;
	private boolean running;
	private Thread theThread;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		theView = (MyView) findViewById(R.id.theView);
		running = false;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public void run() {
		while (running)
			theView.invalidate();
	}
	
	public void go() {
		running = true;
		theThread = new Thread(this);
		theThread.start();	
	}
	
	public void hold() {
		running = false;
		while (true) 
		{
			try {
				theThread.join();
			}
			catch (InterruptedException e) {
				e.printStackTrace();
			}
			break;
		}
		theThread = null;
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		hold();
	}

	@Override
	protected void onResume() {
		super.onResume();
		go();
	}
}

How to update a view from a separate thread

Updating a view from a separate thread will always require to gain access to the main thread to request a change to the view. The view class provides several methods to queue up the update request in the main thread.

You can use for example postinvalidate() from a separate thread to post the update request to the main thread. The following coding shows how the failing coding in the run() method has to be modified to get the desired result.

@Override
public void run() {
	while (running)
		//theView.invalidate();	
		theView.postInvalidate();
}

Another possibility is to use the method runOnUiThread() provided by the activity class to gain access to the main thread. In our case the following coding will allow us to update the view from a separate thread as well.

@Override
public void run() {
	while (running)
	{
                //theView.invalidate();	
		runOnUiThread( new Runnable() {
			public void run() {
				theView.invalidate();
			}
		});
	}
}

Exception from this threading restrictions

The surfaceview is an exception from this threading restrictions as we gain full control over the view from a secondary thread without considering the view hierarchy. This is useful whenever the speed of drawing to a canvas matters, as we are able to draw indepently from the main UI thread as fast as possible.