android - more - EditText causando pérdida de memoria
increasing code cache capacity to 2mb android studio (2)
Introducción:
Tengo una aplicación que tiene la siguiente estructura: ActionBar up top (ActionBarSherlock) ViewPagerIndicator debajo de ese (para pestañas) ViewPager (fragmentos de hosts)
Tengo el problema de que uno de mis fragmentos está causando una pérdida 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
s en él (incluye más cosas normalmente, pero acorté el problema a solo estas vistas para simplificarlo).
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 extiende 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 divertida:
Esto es lo que sucede con el montón cuando giro mi dispositivo de un lado a otro 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 pérdida de memoria. Sí, ya sé que hace que la Actividad se vuelva a crear desde cero y esto es lo que quiero porque tengo diferentes diseños para los modos horizontal y vertical. Sin embargo, no debe causar una pérdida de memoria.
He encontrado la fuente de este problema. Son los dos EditText
que mencioné anteriormente. 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
¡Eso es lo que quiero ver!
¿¡POR QUÉ!?
¿Alguien puede decirme por qué esto está sucediendo? Me gustaría agregar que no EditText
una referencia a este objeto EditText
en ninguna parte de mi aplicación (normalmente lo hago, pero incluso cuando los quité a todos con fines de prueba, la fuga aún ocurre).
Bonus - MAT Capturas de pantalla de la fuga:
Como puede ver, hay 16 instancias del Fragmento Y la Actividad, mientras que solo debe 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 corrige ... Pero ahora son bastante inútiles ...
He encontrado una solución que se adapta a mis necesidades.
widget.EditableInputConnection
el problema a widget.EditableInputConnection
. Que 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 el 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 el InputConnection. Esto elimina las sugerencias y elimina la pérdida de memoria.
Espero que esto te ayude a ..
Me enfrentaba exactamente al mismo problema con un Samsung Galaxy S3.
La solución de @aslakjo no funcionó para mí. Ya tuve sugerencias deshabilitadas
Terminé reemplazando la android:tag
android:id
por android:tag
para EditText
en el diseño XML. Ahora funciona bien, mis fragmentos que estaban contenidos en un viewpager se recogen correctamente cuando ya no están visibles, no me preguntes por qué.
Este dispositivo puede registrar algo en función de la presencia de un id
.