20
votes

In Ice Cream Sandwich, when there's an Activity containing an EditText, the EditText will retain the Activity's Context even after the user leaves the Activity. To demonstrate this I've created TestLeakActivity, which allocates a large byte array. Since the Activity's Context is never garbage collected, the byte arrays accumulate on the heap, eventually causing an OutOfMemoryError. You can observe the heap growth by using the DDMS heap tool, and you can track the outstanding references to the EditText class by looking at the HPROF file in Eclipse MAT. To create memory leaks, go into LaunchActivity and just keep launching and backing out of TestLeakActivity.

LaunchActivity.java
package com.example.testleakproject;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

public class LaunchActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Button button = new Button(this);
        button.setText("Start TestLeakActivity");
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(LaunchActivity.this, TestLeakActivity.class);
                startActivity(intent);
            }
        });

        ViewGroup container = ((ViewGroup) findViewById(android.R.id.content));
        container.addView(button);
    }
}
TestLeakActivity.java
package com.example.testleakproject;

import android.app.Activity;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.EditText;

public class TestLeakActivity extends Activity {
    private byte[] mSomeBytes = new byte[1048576];

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        EditText editText = new EditText(this);
        editText.setHint("TestLeakActivity");

        ViewGroup container = ((ViewGroup) findViewById(android.R.id.content));
        container.addView(editText);
    }
}
6

6 Answers

8
votes

This is a known bug, that will be fixed in ICS MR1.

7
votes

This has not been fixed until now. (Android 4.2.1)

4
votes

I've just spend several hours to find that I'm affected by this issue.

The issue seems to be caused by the spell checker. When I disable suggestions for the EditText view everything is properly garbage collected.

mInputType = mText.getInputType();
mText.setInputType(mInputType | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);

I don't really want to disable this, since many users want spell checking. So, maybe there is a way to temporarily enable it when the input field receives the focus.

If you don't need the spell checker just add this to the EditText element in your layout xml instead:

android:inputType="textNoSuggestions"

That seems to fix it too.

Edit:

Just found this thread that appears to be related: Work around SpellCheckerSession leak?

0
votes

I'm experiencing the same. My Gingerbread devices all work fine, but testing on my Galaxy Nexus this situation arises predictably. What your experiencing is likely why the MR1 and 4.0.3 updates rolled out so quickly.

-2
votes

You are running into the situation described in the Android resources section on memory leaks. See that page for some solutions as well.

-2
votes

I got the same problem, I solved it by hiding the EditText ondismiss of my dialog.

  mEditText.setVisibility(View.GONE);