Jul 23, 2009

Why one has to use a Handler in Android?

Following is inferred from the documentation about a Handler

The handler is used to schedule a runnable on the message queue of the thread that created the handler. it is mostly used to schedule UI updates on the UI thread

The one think I could not understand why I can't use any thread to update UI.

I did some experiment for the same.

Here I tried to update a TextView after every 1 second for 50 seconds using a normal thread and it failed. I got an exception

package org.punegtug.sample;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

public class HandlerTest extends Activity {
private TextView textView = null;
private int index = 0;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);
textView = (TextView) findViewById(R.id.textView);
textView.setText("index="+index);
}

/*
* (non-Javadoc)
*
* @see android.app.Activity#onPause()
*/
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}

/*
* (non-Javadoc)
*
* @see android.app.Activity#onResume()
*/
@Override
protected void onResume() {

Runnable runnable = new Runnable() {

@Override
public void run() {
index = 0;
while (index < 50) {

//Tried to access text from UI component textView
String text= textView.getText().toString();

//Directly tried to update UI in this thread
textView.setText("index="+index++);


try {
// do what you want to do before sleeping
Thread.currentThread().sleep(1000);// sleep for 1000 ms
// do what you want to do after sleeptig
} catch (InterruptedException ie) {
// If this thread was intrrupted by nother thread
}

}

}

};
Thread thread = new Thread(runnable);
thread.start();


}

}

But the following code with Handler worked

t android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

public class HandlerTest extends Activity {
private TextView textView = null;
private int index = 0;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);
textView = (TextView) findViewById(R.id.textView);
textView.setText("index="+index);
}

/*
* (non-Javadoc)
*
* @see android.app.Activity#onPause()
*/
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}

/*
* (non-Javadoc)
*
* @see android.app.Activity#onResume()
*/
@Override
protected void onResume() {
final Handler handler = new Handler(new Handler.Callback() {

@Override
public boolean handleMessage(Message msg) {
textView.setText("index="+index++);
return false;
}
});
Runnable runnable = new Runnable() {

@Override
public void run() {
index = 0;
while (index < 50) {

//Tried to access text from UI component textView
String text= textView.getText().toString();

//Indirectly tried to update UI in this thread
handler.sendEmptyMessage(0);


try {
// do what you want to do before sleeping
Thread.currentThread().sleep(1000);// sleep for 1000 ms
// do what you want to do after sleeptig
} catch (InterruptedException ie) {
// If this thread was intrrupted by nother thread
}

}

}

};
Thread thread = new Thread(runnable);
thread.start();


}

}

So I could, one can not update a UI component in any other thread than UI thread. However, getting values from existing UI components in any thread (e.g textView.getText()) works fine.

Hence we need to use Handler.

Soon, I will send a post about Looper.

No comments:

Post a Comment