我遇到了令人烦恼的内存泄漏和崩溃,这似乎是一个平台错误。我试图调试/另一个/内存问题,但我一直发现这个与EditText相关的错误,保持我的观点以及那些观点。
给定一个DialogFragment,一个带有EditText和UI Monkey的布局我可以通过Out of Memory异常使以下简单的应用程序崩溃。
我已经在x86仿真器17-19上进行了测试,截至2014年3月21日的最新更新为16MB。在4.4.2上的Nexus 4上,我看到内存泄漏在五分钟内增加并增加和增加,但从未让它长到足以看到它崩溃,但在查看N4时会出现相同的泄漏。内存转储。
当按下选项菜单时,Activity会打开DialogFragment:
package org.example.edittextoom;
import android.app.Dialog;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
DialogFragment df = new Df();
df.show(getSupportFragmentManager(), "dialogtag");
return true;
}
public static class Df extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog onCreateDialog = super.onCreateDialog(savedInstanceState);
return onCreateDialog;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Using inflator from app context instead to attempt to avoid the issue with EditTexts holding onto Activity's
View view = LayoutInflater.from(
getActivity().getApplicationContext()).inflate(
R.layout.dialog, container, false);
// Since disabling no suggestions is suppose to prevent the edit text leak
EditText et = (EditText) view.findViewById(R.id.editText1);
int it = et.getInputType();
et.setInputType(it | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
it = et.getInputType();
return view;
}
}
}
这两种布局很简单。对话框有一个EditText。
activity_main.xml中
<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"
>
</RelativeLayout>
dialog.xml
<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" >
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:inputType="text|textNoSuggestions"
/>
</RelativeLayout>
让我们通过运行UI Monkey来查看内存泄漏。
adb shell monkey -p org.example.edittextoom --pct-nav 0 --pct-majornav 0 --pct-appswitch 0 800000
(如果你要运行它,请在屏幕尺寸最小的x86仿真器上运行它以提高速度。)
在它运行的同时,您也可以通过查看第五列来确认它占用的内存越来越多,大约一分钟左右(顺便提一下,它通常会在56000左右崩溃) :
$ adb shell ps | grep edittext
u0_a46 2727 794 177888 31596 ffffffff b7f34997 S com.example.edittextoom
$ adb shell ps | grep edittext
u0_a46 2727 794 177888 31784 ffffffff b7f3322a S com.example.edittextoom
$ adb shell ps | grep edittext
u0_a46 2727 794 177956 31852 ffffffff b7f34997 S com.example.edittextoom
$ adb shell ps | grep edittext
u0_a46 2727 794 178124 32064 ffffffff b7f3322a S com.example.edittextoom
然后它最终会崩溃(我发现的事件150,000到500,000)输出:
// CRASH: com.example.edittextoom (pid 13620)
// Short Msg: java.lang.OutOfMemoryError
// Long Msg: java.lang.OutOfMemoryError
// Build Label: generic_x86/sdk_x86/generic_x86:4.2/JOP40C/eng.android-build.20121231.103448:eng/test-keys
// Build Changelist: eng.android-build.20121231.103448
// Build Time: 1356921334000
// java.lang.OutOfMemoryError
// at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
// at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:502)
// at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:355)
// at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:785)
// at android.content.res.Resources.loadDrawable(Resources.java:1965)
// at android.content.res.Resources.getDrawable(Resources.java:660)
// at com.android.internal.policy.impl.PhoneWindow.generateLayout(PhoneWindow.java:2832)
// at com.android.internal.policy.impl.PhoneWindow.installDecor(PhoneWindow.java:2875)
// at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:285)
// at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:279)
// at android.app.Dialog.setContentView(Dialog.java:482)
// at android.support.v4.app.DialogFragment.onActivityCreated(DialogFragment.java:366)
// at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1508)
// at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:947)
// at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
// at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
// at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
// at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440)
// at android.os.Handler.handleCallback(Handler.java:725)
// at android.os.Handler.dispatchMessage(Handler.java:92)
// at android.os.Looper.loop(Looper.java:137)
// at android.app.ActivityThread.main(ActivityThread.java:5039)
// at java.lang.reflect.Method.invokeNative(Native Method)
// at java.lang.reflect.Method.invoke(Method.java:511)
// at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
// at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
// at dalvik.system.NativeStart.main(Native Method)
//
** Monkey aborted due to error.
Events injected: 131816
:Sending rotation degree=0, persist=false
:Dropped: keys=1534 pointers=13377 trackballs=0 flips=0 rotations=0
## Network stats: elapsed time=308525ms (0ms mobile, 0ms wifi, 308525ms not connected)
** System appears to have crashed at event 131816 of 800000 using seed 1393322223373
(有时模拟器不断占用内存并杀死应用程序,但是你没有得到强制关闭对话,所以UI Monkey进入循环,玩模拟器直到它再次启动应用程序,但无论如何,应用程序在占用了大量内存后被系统杀死。)
如果你停止UI monkey mid flow,通过取消它的过程,你可以检查MAT中的hprof以查看占用内存的内容(我退出应用程序并在查看hprof之前执行强制gc) ,看到它只保留了一个MainPageActivity但是63个实例的MainPageActivity $ Df,并且只运行了一分钟左右。我看到Nexus 4上的内存转储也是一样的。
如果列出对其中一个的传入引用,并单击Path To GC Roots并排除弱引用和软引用,则得到这个(它与我所看到的所有其他63个引用相同) :
但是,如果我将对话框中的EditText更改为带有id或带有id的TextView的ProgressBar,我不会发生此崩溃或MAT中显示的内存泄漏。所以我认为它与这个EditText causing memory leak错误相关,但是,没有任何解决方法可以工作,不会使EditText的InputConnection无效,也不会关闭建议(我已经完成了上面的例子)。如果我删除EditText的id,我也设法摆脱泄漏,但是我无法访问我的EditTexts。
你见过类似的,找到了解决方法,或者你是否可以在我的代码中看到一些疏忽?
此问题目前阻止我在应用程序中正确查找内存泄漏。
答案 0 :(得分:5)
我遇到了同样的问题。由于编辑器内部的Blink,在Dialog中有一个EditText会泄漏内存。这种情况发生在三星Tab 10 4.4.2中,但并不是发生在Nexus 7 4.4.2上,这很奇怪。
绕过它的唯一方法是在EditText中禁用光标。使用setCursorVisible(false)。如果您希望光标闪烁,可以在关闭对话框之前禁用光标,这可以防止Blinker再次安排自己。
注意:rana的建议显然是错误的。他根本不了解静态嵌套类和非静态内部类之间的区别。非静态内部类将保存对您的活动的隐式引用,因此实际上您希望在此处使用静态嵌套类,即SAME在单独的文件中声明此类。
答案 1 :(得分:0)
您可以使用自定义视图替代DialogFragment,或使用对话框
答案 2 :(得分:-1)
将DialogFragment df声明为活动的一部分。你没事。