Why does EditText retain its Activity's Context in Ice Cream Sandwich
在Ice Cream Sandwich中,当有一个包含EditText的Activity时,即使用户离开Activity,EditText也会保留Activity的Context。 为了证明这一点,我创建了TestLeakActivity,它分配了一个大字节数组。 由于Activity的Context不会被垃圾收集,因此字节数组会在堆上累积,最终导致OutOfMemoryError。 您可以使用DDMS堆工具观察堆增长,并且可以通过查看Eclipse MAT中的HPROF文件来跟踪对EditText类的未完成引用。 要创建内存泄漏,请进入LaunchActivity,然后继续启动并退出TestLeakActivity。
1 | LaunchActivity.java |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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); } } |
1 | TestLeakActivity.java |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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); } } |
这是一个已知错误,将在ICS MR1中修复。
直到现在还没有修复。 (Android 4.2.1)
我只花了几个小时才发现我受这个问题的影响。
这个问题似乎是由拼写检查引起的。当我禁用EditText视图的建议时,一切都被正确地垃圾收集。
1 2 | mInputType = mText.getInputType(); mText.setInputType(mInputType | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); |
我真的不想禁用它,因为许多用户想要拼写检查。因此,当输入字段获得焦点时,可能有一种临时启用它的方法。
如果您不需要拼写检查器,只需将其添加到布局xml中的EditText元素:
1 | android:inputType="textNoSuggestions" |
这似乎也解决了这个问题。
编辑:
刚刚发现这个线程似乎是相关的:解决SpellCheckerSession泄漏问题?
我也遇到了同样的问题。我的姜饼设备都运行良好,但在我的Galaxy Nexus上测试这种情况可以预见。您的体验可能是为什么MR1和4.0.3更新如此迅速地推出。
我遇到了同样的问题,
我通过隐藏EditText ondismiss对话来解决它。
1 | mEditText.setVisibility(View.GONE); |
您正在遇到关于内存泄漏的Android资源部分中描述的情况。有关某些解决方案,请参阅该页面。