System.gc () provocando una desaceleración desde el segundo inicio de la Actividad

Estoy experimentando un fenómeno muy extraño (dispositivo de prueba: HTC Desire HD, Android 2.3.5). Sé que System.gc() es necesario y desalentado, y no trato de sugerir lo contrario, pero el punto es que no debe causar problemas tampoco (es decir, debe ser inútil a lo sumo ).

Tengo una aplicación que contiene un GLSurfaceView en su jerarquía de la visión. GLSurfaceView se instancia y se agrega en Activity.onCreate() . Normalmente, la aplicación funciona de la siguiente manera:

  1. El usuario inicia la aplicación y va al menú principal.
  2. El usuario elige un elemento mainmenu que fija GLSurfaceView a View.VISIBLE
  3. El usuario juega con el juego incorporado en GLSurfaceView
  4. El usuario va al mainmenu y sale de la actividad (=> Activity.finish() se llama)

Mi Activity.onPause() tiene este aspecto:

 mGameThread.pause(); // gameThread is my custom thread class for the in-built game mGLView.onPause(); // pause the renderer thread 

Hasta ahora todo bien, todo funciona bien. Sin embargo, aparecen problemas después de agregar el siguiente código a onPause() (para el caso en que el usuario abandone el juego desde el mainmenu):

 mGameThread.pause(); // gameThread is my custom thread class for the in-built game mGLView.onPause(); // pause the renderer thread if (isFinishing()) { System.gc(); } 

En detalles: si la Activity se inicia por primera vez (= es decir, el proceso de aplicación no existía antes), todo funciona bien. Sin embargo, a partir del segundo inicio de la actividad (= después de la primera salida del mainmenu, es decir, después de la primera Activity.finish() ), el framerate de GLSurfaceView se reduce en un 40-50% , el juego incorporado se vuelve lento .

Si System.gc() llamada System.gc() , el problema desaparece. Por otra parte, si hago lo siguiente, también se deshace del problema:

 mGameThread.pause(); // gameThread is my custom thread class for the in-built game mGLView.onPause(); // pause the renderer thread if (isFinishing()) { // 1. get layout root of View hierarchy // 2. recursively remove (detach) all Views // 3. call GC System.gc(); } 

No agregué código concreto porque es complejo, así que usé comentarios. Si acabo de separar el GLSurfaceView través de removeView() , no es suficiente. La jerarquía de vista completa necesita ser borrada.

Tenga en cuenta que no pude encontrar ninguna pérdida de memoria (no hay fugas de actividad a través de drawables / statics, etc.). Por otra parte, por supuesto, el gameThread sale correctamente cuando la aplicación se cierra (no incluí su código fuente).

¿Ideas, conjeturas? Al parecer, System.gc() parece causar algunos problemas para el mecanismo de destrucción de la actividad / diseño de Android. Una vez más, como he dicho, si quito System.gc() , el problema desaparece.

Tengo la experiencia de la programación del juego de Androide. Solía ​​borrar toda la vista en jerarquía porque cuando se ejecuta hilos si llama a System.gc () a veces sucede que su hilo tiene una referencia a algunas de sus vistas, incluso si llama a system.gc () esta vista no Obtener eliminado y si sigue jugando una y otra vez este juego se dará cuenta de que su memoria montón se ha comenzado a crecer.

Depende de la fuga de memoria, si usted está goteando algunos KB memoria que tomará más tiempo para estrellarse su juego. La mejor manera de usar Eclipse Memory Anlyser (Eclipse MAT) y comparar sus pilas.

Step1: tomar la memoria snap shot cuando inicie su juego por primera vez Paso 2: tomar memoria snap shot cuando se inicia el juego de segunda vez Paso 3: Ahora comparar sus dos pilas de instantáneas le dirá la diferencia.

Es una herramienta muy útil. Estaba teniendo enormes problemas de memoria en mi juego Apache Attack . Los arreglé usando esta herramienta impresionante. Siga este TUTORIAL de MAT de ECLIPSE

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.