Android Handler Example

Carlos Gómez
devops and cross platform development
3 min readJun 3, 2014

--

A Handler allows send and process Message and Runnable objects associated with a thread’s looper MessageQueue. Each Handler instance is associated with a single thread and that thread’s message queue.

Android Handler Message Queue

A Handler provides several capabilities to applications:

  • Sends messages and posts runnables to a thread’s looper.
  • Collaborates with looper to serialize the processing of messages in a thread

Creating the Project

Let’s create a simple android handler, this example downloads an image from an url after push a button and show it in an imageview, we are going to use a handler to establish a communication with the UI thread.

Launch Eclipse and create an Android Application Project named HandlerApp with the appropriate package name and SDK selections. Select blank activity.

Edit the main layout

Add the button and the imageview.

<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.devcfgc.handler.MainActivity" >
<Button
android:id="@+id/btnStartHandler"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="@string/btn_get_image" />
<ImageView
android:id="@+id/showImage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="@+id/btnStartHandler"
android:layout_centerHorizontal="true"
android:contentDescription="@string/description_image" />
</RelativeLayout>Code the MainActivity to get the imageTo fix possible memory leaks in the MainActivity we need to use a static inner class for the Handler, the static inner classes do not hold an implicit reference to their outer class, so the activity will not be leaked.
If you need to invoke the outer activity's methods from within the Handler, the Handler have to hold a WeakReference to the activity so you don't accidentally leak a context.
More info in http://stackoverflow.com/questions/11278875/handlers-and-memory-leaks-in-android
public class MainActivity extends Activity {private static ProgressDialog progressDialog;
private static ImageView imageView;
private String url = "http://www.devcfgc.com/wp-content/uploads/2014/06/Android_Handler.jpg";
private static Bitmap bitmap = null;
private final ImageHandler mHandler = new ImageHandler(this);
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.showImage);Button start = (Button) findViewById(R.id.btnStartHandler);
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
progressDialog = ProgressDialog.show(MainActivity.this, "",
"Loading..");
new Thread() {
public void run() {
bitmap = downloadBitmap(url);
mHandler.sendEmptyMessage(0);
}
}.start();
}
});
}
/**
* Instances of static inner classes do not hold an implicit reference to
* their outer class.
*
* To fix possible memory leaks in the MainActivity we need to use a static inner class for the Handler.
* Static inner classes do not hold an implicit reference to their outer class, so the activity
* will not be leaked. If you need to invoke the outer activity's methods from within the Handler,
* have the Handler hold a WeakReference to the activity so you don't accidentally leak a context.
* More info in http://stackoverflow.com/questions/11278875/handlers-and-memory-leaks-in-android
*/
private static class ImageHandler extends Handler {
private final WeakReference<MainActivity> mActivity;
public ImageHandler(MainActivity activity) {
mActivity = new WeakReference<MainActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
if (mActivity == null) {
throw new RuntimeException("Something goes wrong.");
} else {
imageView.setImageBitmap(bitmap);
progressDialog.dismiss();
}
}
}
private Bitmap downloadBitmap(String url) {
// Initialize the default HTTP client object
final DefaultHttpClient client = new DefaultHttpClient();
// forming a HttoGet request
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);// check 200 OK for success
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageHandler", "Error " + statusCode
+ " retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
// getting contents from the stream
inputStream = entity.getContent();
// decoding stream data back into image Bitmap
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
getRequest.abort();
}
return null;
}
}
Check the source code in github: https://github.com/android-devcfgc/HandlerExample-Android

--

--

Cloud/Software Architect and DevOps learning about #devops, #cloud, #netcore, #microservices and #newtech