with viewpager studio fragments example android android-fragments android-viewpager

android - viewpager - Cómo destruir fragmentos viejos en FragmentStatePagerAdapter



tabs android (6)

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(); }

Quiero implementar esto:
Uso ViewPager con FragmentStatePagerAdapter.
Empecé con el ejemplo de esta página:
http://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html

Este es mi adaptador ViewPager:

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 cambie a una nueva página en ViewPager, aumentará la memoria RAM muy rápidamente.
¿Cómo debo eliminar los viejos fragmentos?
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 retraso de 1-2 segundos después de cambiar rápidamente a una nueva página o página anterior. ¿Hay alguna técnica para eliminar esa demora? Si cambio a una nueva página y espero durante 2 segundos, en el próximo cambio no habrá más demora.

Probado en Nexus 7.


Creo que el problema no es con ViewPager está en 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 editando esta respuesta.


El FragmentStatePagerAdapter ya es muy frugal con la memoria, ya que destruye los fragments innecesarios de forma automática. Simplemente mantiene las vistas de los fragmentos directamente a la izquierda y derecha del elemento que se muestra actualmente y destruye las demás.

Ejemplo: Entonces, una vez que deslizas hacia la dirección correcta, precarga el fragmento que pronto quedará a la derecha y destruye el fragmento que ahora está a dos ranuras a la izquierda del fragmento mostrado actualmente.


No deberías tratar de interferir con la forma en que Android administra tus implementaciones de Fragment . El valor predeterminado para setOffScreenPageLimit ya debería ser uno. Esto significa que Android destruirá fragmentos viejos cuando la memoria se agote. Mientras no tengas un problema de memoria, solo déjalo.

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

La demora que está experimentando podría deberse a un cálculo intenso en el hilo de la interfaz de usuario. Si es así, te sugiero que lo AsyncTask a, por ejemplo, una AsyncTask . Sin el código, sin embargo, solo se trata de adivinar qué podría causar el problema. Pero al haber solo una demora inicial, sugiere que está cargando algo que podría bloquear el hilo de UI.

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


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

Es un poco difícil decir cuál puede ser su problema particular porque no sé lo que hace su fragmento. Por el sonido de la demora de 1-2 segundos parece que podrías estar trabajando en el hilo de la interfaz de usuario. Además, ¿qué más estás haciendo en tu fragmento que consume memoria? ¿Tal vez estás cargando imágenes en algún caché de memoria estática y no las liberas al eliminar fragmentos? ¿Podrías proporcionar tu código de fragmento para ver qué está haciendo?

En general, recomendaría que se descargue un archivo HPROF de su aplicación en el momento en que se requiera memoria extra y se analicen las referencias mediante MAT (herramienta de análisis de memoria). Está claro que tiene problemas de pérdida de memoria y dudo mucho que el problema esté en que los Fragmentos no se destruyan.

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.


Yo tuve el mismo problema. Pero en mi caso ViewPager estaba dentro del otro fragmento. y después de eliminar ViewPagerFragment de FragmentManager, todos los fragmentos de FragmentStatePagerAdapter se mantienen en el administrador de fragmentos. entonces, después de algunos de esos cambios, fue OutOfMemoryError. Luego enciendo los registros de FragmentManager por:

FragmentManager.enableDebugLogging(true);

Y descubrió que la identificación de cada fragmento nuevo aumenta cada vez. Sucede solo con StatePagerAdapter. Para resolver este problema, llamo eliminar para cada fragmento que se haya instanciado.

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 ese recolector de basura no pueda destruir sus fragmentos incluso después de eliminarlos del administrador de fragmentos debido a algunas referencias a ellos. Debería verificar si algunas clases globales los usan.

Y para fines de optimización, puede almacenar en caché cada fragmento instanciado mediante 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); } } }