Avoiding Android Memory Leaks: Part 1

I recently discovered how easy it is to accidentally “leak” memory and resources in an Android application.

In this tutorial, I’ll illustrate a memory leak with a simple dialog box example, and then show you how to fix it.

Let’s start by creating a simple Android application that displays a dialog in its onCreate event:

[java]
package com.justinschultz.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;

public class LeakedDialogActivity extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setMessage("This dialog leaks!").setTitle("Leaky Dialog").setCancelable(false).setPositiveButton("Ok", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which) {}
});

AlertDialog alert = builder.create();
alert.show();
}
}
[/java]

If you’ve copied this correctly, the app should look like this:

Leaky Android Dialog

While this application is running, take a look in LogCat. (In Eclipse, LogCat can be displayed via Window -> Show View -> LogCat.)

While the dialog is displayed, rotate the device (or the emulator by pressing CTRL+F11).

You should see a lot of bright red error text in LogCat that looks something like this:

LogCat Leaked Window Error

Even though it looks like everything is working correctly on the device, LogCat displays this error message:
[java wraplines=”true”]
Activity com.justinschultz.android.LeakedDialogActivity has leaked
window com.android.internal.policy.impl.PhoneWindow$DecorView@40543ec0
that was originally added here
[/java]

So… what happened?

When the device rotates, the onPause and onStop Activity events are invoked. Then a new landscape Activity is created, and its onCreate method is invoked.

Since the dialog is displayed and has a reference to the Activity, it can’t be garbage collected, and subsequently is leaked. That is, you’ve created an object that can’t be garbage collected.

To fix this, let’s make the dialog an Activity member variable and override the onPause method to dismiss it:

[java]
AlertDialog _alert;

@Override
public void onPause() {
super.onPause();

if(_alert != null)
_alert.dismiss();
}
[/java]

This will dismiss the dialog each time the Activity is destroyed and recreated and the error will magically disappear from LogCat.

Here’s the source for this example.

Comments

2 responses to “Avoiding Android Memory Leaks: Part 1”

  1. Jouko Kaasila Avatar

    This is a great post and very useful for every Android developer. There is another blog post about how Justin’s team were able to reproduce and find the root cause of this memory leak here. Please take a look.

  2. Manju Avatar
    Manju

    Short and very informative article ….Keep the good work going

Leave a Reply

Your email address will not be published. Required fields are marked *