EditText que causa pérdida de memoria

Introducción:

Tengo una aplicación que tiene la siguiente estructura: ActionBar arriba (ActionBarSherlock) ViewPagerIndicator debajo de eso (para tabs) ViewPager (hosts Fragmentos)

Tengo el problema de que uno de mis fragmentos está causando una fuga de memoria bastante importante. Reduje el problema al siguiente caso:

El fragmento que está causando la fuga no hace más que inflar un diseño en su método onCreateView . Esto se hace de la siguiente manera:

 return inflater.inflate(R.layout.filter_auctions_fragment, container, false); 

Nada inusual aquí.

El archivo de diseño solo incluye un ScrollView , LinearLayout y dos EditText en él (incluye más cosas normalmente, pero reduje el problema a solo estas vistas para hacerlo simple).

Ahora el código que se usa para agregar el fragmento: mTabsAdapter.addTab (tabName, ProblematicFragment.class);

mTabsAdapter es una instancia de TabsAdapter , una clase que amplía FragmentPagerAdapter de la biblioteca de soporte. Es bastante estándar, así que no incluyo la fuente para mantener esta pregunta lo más breve posible.

Ahora la parte graciosa:

Esto es lo que sucede con el montón cuando giro mi dispositivo hacia adelante y hacia atrás varias veces:

 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 888K, 9% free 11919K/12984K, paused 4ms+5ms, total 52ms 12-28 12:26:31.810: D/dalvikvm(18841): GC_CONCURRENT freed 903K, 8% free 12421K/13500K, paused 3ms+8ms, total 58ms 12-28 12:26:33.800: D/dalvikvm(18841): GC_CONCURRENT freed 1092K, 9% free 13005K/14272K, paused 4ms+6ms, total 59ms 12-28 12:26:33.800: D/dalvikvm(18841): WAIT_FOR_CONCURRENT_GC blocked 20ms 12-28 12:26:36.000: D/dalvikvm(18841): GC_CONCURRENT freed 1355K, 11% free 13518K/15048K, paused 3ms+8ms, total 74ms 12-28 12:26:36.000: D/dalvikvm(18841): WAIT_FOR_CONCURRENT_GC blocked 19ms 12-28 12:26:38.110: D/dalvikvm(18841): GC_CONCURRENT freed 1450K, 11% free 14106K/15720K, paused 3ms+11ms, total 72ms 12-28 12:26:40.450: D/dalvikvm(18841): GC_CONCURRENT freed 1530K, 11% free 14807K/16516K, paused 2ms+15ms, total 75ms 12-28 12:26:40.450: D/dalvikvm(18841): WAIT_FOR_CONCURRENT_GC blocked 29ms 12-28 12:26:43.030: D/dalvikvm(18841): GC_CONCURRENT freed 1682K, 11% free 15591K/17452K, paused 3ms+10ms, total 66ms 12-28 12:26:43.030: D/dalvikvm(18841): WAIT_FOR_CONCURRENT_GC blocked 32ms 

Claramente, una fuga de memoria. Sí, sé que hace que la actividad se recree desde cero y esto es lo que quiero porque tengo diferentes diseños para los modos de paisaje y retrato. Sin embargo, no debería causar una pérdida de memoria.

He encontrado la fuente de este problema. Son los dos EditText que mencioné antes. Tan pronto como los elimine del diseño y haga la misma prueba (gire hacia adelante y hacia atrás). Estos son los mensajes de GC que recibo:

 12-28 12:21:41.270: D/dalvikvm(17934): GC_CONCURRENT freed 534K, 7% free 10853K/11576K, paused 3ms+7ms, total 44ms 12-28 12:21:42.560: D/dalvikvm(17934): GC_CONCURRENT freed 818K, 9% free 11113K/12108K, paused 11ms+9ms, total 95ms 12-28 12:21:44.680: D/dalvikvm(17934): GC_CONCURRENT freed 1036K, 10% free 11313K/12528K, paused 3ms+6ms, total 54ms 12-28 12:21:44.680: D/dalvikvm(17934): WAIT_FOR_CONCURRENT_GC blocked 15ms 12-28 12:21:47.420: D/dalvikvm(17934): GC_CONCURRENT freed 1089K, 10% free 11510K/12780K, paused 2ms+6ms, total 79ms 12-28 12:21:47.420: D/dalvikvm(17934): WAIT_FOR_CONCURRENT_GC blocked 39ms 12-28 12:21:50.200: D/dalvikvm(17934): GC_CONCURRENT freed 1317K, 12% free 11461K/12956K, paused 4ms+13ms, total 84ms 12-28 12:21:53.210: D/dalvikvm(17934): GC_CONCURRENT freed 1629K, 14% free 11148K/12956K, paused 3ms+7ms, total 47ms 12-28 12:21:55.580: D/dalvikvm(17934): GC_CONCURRENT freed 1056K, 13% free 11302K/12956K, paused 4ms+7ms, total 59ms 12-28 12:21:57.280: D/dalvikvm(17934): GC_CONCURRENT freed 1306K, 14% free 11200K/12956K, paused 5ms+5ms, total 82ms 12-28 12:21:59.420: D/dalvikvm(17934): GC_CONCURRENT freed 1035K, 12% free 11408K/12956K, paused 3ms+7ms, total 55ms 12-28 12:22:01.990: D/dalvikvm(17934): GC_CONCURRENT freed 1392K, 13% free 11352K/12956K, paused 4ms+9ms, total 54ms 12-28 12:22:01.990: D/dalvikvm(17934): WAIT_FOR_CONCURRENT_GC blocked 30ms 

¡Ahora eso es lo que quiero ver!

¿¡POR QUÉ!?

¿Alguien puede decirme por qué sucede esto? Me gustaría agregar que no estoy manteniendo una referencia a estos objetos EditText en ninguna parte de mi aplicación (normalmente lo hago, pero incluso cuando los EditText para fines de prueba, la filtración aún ocurre).

Bonus – MAT Capturas de pantalla de la fuga:

Camino a las raíces de GC (sin referencias suaves / débiles) para mi actividad

Como puede ver, hay 16 instancias del Fragmento Y la Actividad, mientras que solo debería haber una.

EDITAR:

Noté que cuando agrego manualmente el fragmento en una actividad diferente (usando FragmentManager.beginTransaction() ) la fuga no ocurre. Estoy completamente confundido ahora …

EDIT2:

Eliminar el atributo android:id de EditText s lo soluciona … Pero ahora son bastante inútiles …

He encontrado una solución que se ajusta a mis necesidades.

Seguí el problema hasta widget.EditableInputConnection . Lo cual creo que hace la búsqueda en el sistema de sugerencias. También es responsable de aferrarse a mi actividad, lo que provoca una pérdida de memoria.

No necesito las sugerencias, así que quise apagarlo. Sin embargo, ha demostrado ser difícil. EditText.setInputType no funcionó, ni en xml ni en código.

Terminé haciendo lo siguiente. La magia está sucediendo en onCreateInputConnection() :

 public class MyEditText extends TextView { public MyEditText(Context context) { this(context, null); } public MyEditText(Context context, AttributeSet attrs) { this(context, attrs, android.R.attr.editTextStyle); } public MyEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { return null; } @Override protected boolean getDefaultEditable() { return true; } @Override protected MovementMethod getDefaultMovementMethod() { return ArrowKeyMovementMethod.getInstance(); } @Override public Editable getText() { return (Editable) super.getText(); } @Override public void setText(CharSequence text, BufferType type) { super.setText(text, BufferType.EDITABLE); } /** * Convenience for {@link Selection#setSelection(Spannable, int, int)}. */ public void setSelection(int start, int stop) { Selection.setSelection(getText(), start, stop); } /** * Convenience for {@link Selection#setSelection(Spannable, int)}. */ public void setSelection(int index) { Selection.setSelection(getText(), index); } /** * Convenience for {@link Selection#selectAll}. */ public void selectAll() { Selection.selectAll(getText()); } /** * Convenience for {@link Selection#extendSelection}. */ public void extendSelection(int index) { Selection.extendSelection(getText(), index); } @Override public void setEllipsize(TextUtils.TruncateAt ellipsis) { if (ellipsis == TextUtils.TruncateAt.MARQUEE) { throw new IllegalArgumentException("EditText cannot use the ellipsize mode " + "TextUtils.TruncateAt.MARQUEE"); } super.setEllipsize(ellipsis); } } 

Donde el truco es rechazar la InputConnection. Esto elimina las sugerencias y elimina la pérdida de memoria.

Espero que esto te ayude a …

Estaba enfrentando exactamente el mismo problema con un Samsung Galaxy S3.

La solución de @aslakjo no funcionó para mí. Ya tuve sugerencias desactivadas

Terminé reemplazando android:id por android:tag para EditText en el diseño XML. Ahora está funcionando bien, mis fragmentos que estaban contenidos en un viewpager son basura recogida correctamente cuando ya no están visibles, no me pregunten por qué.

Este dispositivo puede registrar algo en función de la presencia de una id .