Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Cómo destruir fragmentos antiguos en FragmentStatePagerAdapter

Quiero implementar esto: Introduzca aquí la descripción de la imagen
Utilizo un ViewPager con un FragmentStatePagerAdapter.
Comencé con el ejemplo de esta página:
Http://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html

Este es mi adaptador ViewPager:

  • Android ZXing Obtener imagen de código de barras
  • Notificación personalizada de Android que no muestra cambios de código
  • Prueba de unidad de Android con Retrofit2 y Mockito o Robolectric
  • Cómo eliminar el espacio superior y inferior en la vista de texto de Android
  • ¿Cómo hacer que el menú de aplicaciones de Facebook sea nuevo en Android?
  • ¿Qué hace realmente google-services.json?
  • public static class MyAdapter extends FragmentStatePagerAdapter { public MyAdapter(FragmentManager fm) { super(fm); } @Override public int getCount() { return NUM_ITEMS; } @Override public Fragment getItem(int position) { return ArrayListFragment.newInstance(position); } @Override public void destroyItem(ViewGroup container, int position, Object object) { super.destroyItem(container, position, object); } } 

    Cada página de mi ViewPager contiene un ListView con algunos datos. En el momento en que cambio a una nueva página en ViewPager aumentará la memoria RAM muy rápidamente.
    ¿Cómo debo eliminar los fragmentos antiguos?
    También usé esto pero no hace nada:

     public void destroyItem(ViewGroup container, int position, Object object) { FragmentManager manager = ((Fragment) object).getFragmentManager(); FragmentTransaction trans = manager.beginTransaction(); trans.remove((Fragment) object); trans.commit(); super.destroyItem(container, position, object); } 

    También hay un retardo de 1-2 segundos después de cambiar rápidamente a una nueva página o una página antigua. ¿Hay alguna técnica para eliminar ese retraso. Si cambio a una nueva página y espero por 2 segundos entonces en el interruptor siguiente no hay más demora.

    Probado en Nexus 7.

  • Posición del botón de Android mediante programación
  • Envío de un archivo pdf al cliente desde el servidor a través del servicio web
  • Cómo crear un diseño de superposición en una vista de lista
  • ¿Es posible ocultar / cambiar el número de móvil del remitente mientras se envía sms en android?
  • Ciclo de vida de la actividad - recibir notificación de que el diseño está completo
  • Integración de jpct-ae con el motor Vuforia de Qualcomm en android
  • 6 Solutions collect form web for “Cómo destruir fragmentos antiguos en FragmentStatePagerAdapter”

    No debes intentar interferir en cómo Android gestiona tus implementaciones de Fragment . El valor predeterminado para setOffScreenPageLimit ya debería ser uno. Esto significa que Android destruirá fragmentos antiguos cuando la memoria se agota. Mientras no tengas un problema de memoria, solo déjalo ser.

    La razón por la que aumenta la memoria es porque Android mantiene las instancias de Fragment en la memoria para poder volver a conectarse a ellas en lugar de tener que instanciarlas. Te recomiendo que tengas en cuenta la contingencia de tus Fragment instancias que están siendo destruidas por el sistema operativo, guardando su estado si eso sucede, y dejar que el sistema operativo hacer su trabajo.

    El retraso que está experimentando podría deberse a algún cálculo intensivo en el subproceso de interfaz de usuario. Si es así, sugiero mover eso a, por ejemplo, un AsyncTask . Sin el código es, sin embargo, sólo una suposición de lo que podría causar el problema. Pero habiendo sólo un retraso inicial sugiere que está cargando algo que podría bloquear el subproceso de la interfaz de usuario.

    Actualización : echa un vistazo a https://stackoverflow.com/a/9646622/170781 que describe muy bien cómo el ViewPager maneja las instancias de Fragment .

    Yo tuve el mismo problema. Pero en mi caso ViewPager estaba dentro del otro fragmento. Y después de quitar ViewPagerFragment de FragmentManager, todos los fragmentos de FragmentStatePagerAdapter permanece en el administrador de fragmentos. Así que después de algunos de estos cambios fue OutOfMemoryError. A continuación, activar los registros de FragmentManager por:

     FragmentManager.enableDebugLogging(true); 

    Y encontró que la identificación de cada nuevo fragmento aumenta cada vez. Sucede sólo con StatePagerAdapter. Para solucionar este problema llamo remove para cada fragmento que fue instantáneo.

     protected void dispatchOnDetach(Iterable<Fragment> fragments) { if (fragments == null) return; Activity aa = getActivity(); if (aa == null) return; IBaseActivity ba = (IBaseActivity) aa; if (ba.isActivityStopped()) return; FragmentManager frMan = ba.getSupportFragmentManager(); FragmentTransaction frTr = frMan.beginTransaction(); for (Fragment fr : fragments) { if (fr != null) { frTr.remove(fr); } } frTr.remove(this); frTr.commit(); } 

    En tu caso. Si no cambia ViewPager durante el tiempo de ejecución es posible, que el recolector de basura no puede destruir sus fragmentos incluso después de quitar del encargado del fragmento debido a algunas referencias a ellos. Debería comprobar si algunas clases globales las utilizan.

    Y para propósitos de optimización puede almacenar en caché cada fragmento instantáneo utilizando SoftReference o LruCache. Ejemplo:

     public class MyAdapter extends FragmentStatePagerAdapter { private final LruCache<Integer, Fragment> mCache; public MyAdapter(FragmentManager fm) { super(fm); mCache = new LruCache<Integer, Fragment>(10); } @Override public int getCount() { return NUM_ITEMS; } @Override public Fragment getItem(int position) { return mCache.get(position); } @Override public void destroyItem(ViewGroup container, int position, Object object) { super.destroyItem(container, position, object); } private class MyCache extends LruCache<Integer, Fragment> { public MyCache(int maxSize) { super(maxSize); } @Override protected Fragment create(Integer key) { return ArrayListFragment.newInstance(key); } } } 

    El FragmentStatePagerAdapter ya es muy frugal con la memoria, ya que destruye los fragments innecesarios automáticamente. Simplemente mantiene las vistas de los fragmentos directamente a la izquierda y derecha del elemento actualmente mostrado y destruye a los otros.

    Ejemplo: Una vez que se desliza hacia la dirección correcta, se carga previamente el fragmento de vecindad correcto y se destruye el fragmento que ahora tiene dos ranuras a la izquierda del fragmento que se muestra actualmente.

    Creo que el problema no es con el ViewPager está en el ListFragments. ¿Qué tipo de contenido muestra en ellos? ¿Asignas muchas imágenes? ¿Puedes publicar el código de tu ListFragment?

    Preferiría hacer un comentario, pero como no tengo suficientes puntos, espero ayudar a editar esta respuesta.

    ViewPager tiene un método setOffscreenPageLimit que le permite especificar el número de páginas guardadas por el adaptador. Así que sus fragmentos que están lejos serán destruidos.

    Es un poco difícil decir cuál puede ser su problema particular porque no sé qué hace su fragmento. Por el sonido de 1-2 segundos de retraso parece que podría estar haciendo algún trabajo en el hilo de la interfaz de usuario. ¿También qué más estás haciendo en tu fragmento que consuma memoria? Tal vez usted está cargando imágenes a algún caché de memoria estática y no liberarlos después de la eliminación de fragmentos? ¿Podría por favor proporcionar su código de fragmento, para que yo pudiera ver lo que está haciendo?

    En general, recomendaría descargar un archivo HPROF de su aplicación en el momento que tomó más memoria y analizar las referencias a través de MAT (herramienta de análisis de memoria). Usted está claramente teniendo problemas de fugas de memoria y dudo mucho que el problema está en Fragmentos en sí no ser destruido.

    En caso de que no sepa cómo analizar el montón de memoria, aquí hay un buen video . No puedo contar cuántas veces me ayudó a identificar y eliminar las pérdidas de memoria en mis aplicaciones.

    Anule esto en FragmentStatePagerAdapter, observe el ligero cambio.

     @Override public void destroyItem(ViewGroup container, int position, Object object) { if (position >= getCount()) { FragmentManager manager = ((Fragment) object).getFragmentManager(); FragmentTransaction trans = manager.beginTransaction(); trans.remove((Fragment) object); trans.commit(); } 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.