在Ice Cream Sandwich中,当有一个包含EditText的Activity时,即使用户离开Activity,EditText也会保留Activity的Context.为了证明这一点,我创建了TestLeakActivity,它分配了一个大字节数组.由于Activity的Context不会被垃圾收集,因此字节数组会在堆上累积,最终导致OutOfMemoryError.您可以使用DDMS堆工具观察堆增长,并且可以通过查看Eclipse MAT中的HPROF文件来跟踪对EditText类的未完成引用.要创建内存泄漏,请进入LaunchActivity,然后继续启动并退出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; …
介绍:
我有一个具有以下结构的应用程序:ActionBar up top(ActionBarSherlock)ViewPagerIndicator(用于标签)ViewPager(hosts Fragments)
我有一个问题,我的一个片段导致相当大的内存泄漏.我将问题缩小到以下情况:
导致泄漏的碎片只会在其onCreateView方法中使布局膨胀.这是通过以下方式完成的:
return inflater.inflate(R.layout.filter_auctions_fragment, container, false);
Run Code Online (Sandbox Code Playgroud)
这里没什么不寻常的.
布局文件只包括一个ScrollView,LinearLayout两个EditText,它出现(包括更正常的东西,但我将问题范围缩小到只有这些意见,以使简单).
现在用于添加片段的代码:mTabsAdapter.addTab(tabName,ProblematicFragment.class);
mTabsAdapter是一个TabsAdapter扩展FragmentPagerAdapter支持库的类的实例.它是相当标准的,所以我不包括使这个问题尽可能短的来源.
现在有趣的部分:
这是当我来回旋转设备几次时堆发生的事情:
12-28 12:26:27.180: D/dalvikvm(18841): GC_CONCURRENT freed 530K, 7% free 10701K/11436K, paused 4ms+7ms, total 58ms
12-28 12:26:27.180: D/dalvikvm(18841): WAIT_FOR_CONCURRENT_GC blocked 24ms
12-28 12:26:28.270: D/dalvikvm(18841): GC_CONCURRENT freed 737K, 8% free 11048K/11964K, paused 4ms+5ms, total 53ms
12-28 12:26:29.510: D/dalvikvm(18841): GC_CONCURRENT freed 789K, 8% free 11464K/12436K, paused 5ms+5ms, total 42ms
12-28 12:26:30.640: D/dalvikvm(18841): GC_CONCURRENT freed …Run Code Online (Sandbox Code Playgroud) 我注意到我的一个活动内存增加了奇怪.因此我进行了一些测试:我多次打开对话框(打开 - 关闭 - 打开 - 关闭....)并且内存不断增加.所以我使用DDMS转储HPROF文件并在MAT(Memory analyzer)中打开它.漏洞可疑报告指出,内存消耗增长的主要原因是:

所以我做了一个直方图,检查我运行测试的对话框是什么让它保持活力.事实证明,它通过它的AutoCompleteTextViews保持活跃,而后者又由android.widget.TextView $ IClipboardDataPasteEventImpl保持活着.但是IClipboardDataPasteEventImpl没有直接的支配者(GC当然除外).我试图在互联网上找到IClipboardDataPasteEventImpl并且我搜索了grepcode(android源码),但我唯一想到的就是这个博客条目.我无法阅读任何语言,但我能读到的是投入的英文单词,这表明它可能是三星Galaxy SII(我正在使用的手机,运行android 2.3.x)上的一个错误,与ClipboardManager相关.但是我不确定这个(我想解决这个问题,因此我不愿意接受它只是一个无法修复的错误)而且我不知道这个剪贴板产生的原因和原因.我非常感谢有关此事的任何指示/想法.
我们有活动和碎片泄漏,并将原因追溯到TextViews上看起来未被移除的ChangeWatchers.
场景:活动A启动活动B. B在其布局中有一个textPassword EditText字段.活动B结束.
HPROF转储显示活动B仍然有一个实例.其gcroot路径如下:
test.maa.LoginActivity
'- mContext android.widget.EditText
'- this$0 android.widget.TextView$ChangeWatcher
'- [1] java.lang.Object[13]
'- mSpans android.text.SpannableStringBuilder
'- mSource android.text.method.PasswordTransformationMethod$PasswordCharSequence
'- mText android.text.MeasuredText
'- mMeasured android.text.StaticLayout
'- sStaticLayout class android.text.DynamicLayout
Run Code Online (Sandbox Code Playgroud)
如果您将Linkify.addLinks链接到TextView,也会发生这种情况.
有没有办法清理活动B?
首先,我来自iOS环境,所以这就是为什么这个问题可能很明显的原因.
我知道Android有Garbage Collector,但是对象仍然引用(保留)其他对象,我的理解是GC只会删除一个没有引用的对象(可能我在这一点上错了).看看这段代码:
private void addDefaultTextWatcher(final EditText editText) {
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
value = s.toString();
if (getOnValidate() != null) {
getOnValidate().validate(editText, s.toString());
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
editText有一个TextWatcher匿名类的引用,并且该类也有引用editText.垃圾收集者会为我照顾这个吗?如果没有......建议的方法是什么?
android ×5
memory-leaks ×3
android-4.0-ice-cream-sandwich ×1
android-ui ×1
heap ×1
java ×1
memory ×1