2011-05-23 11 views

Respuesta

106

Parece que la API actualmente echa de menos un método como "getFragments".
Sin embargo, utilizando el evento "onAttachFragment" de la clase Activity debería ser bastante fácil hacer lo que quiera. Me gustaría hacer algo como:

List<WeakReference<Fragment>> fragList = new ArrayList<WeakReference<Fragment>>(); 
@Override 
public void onAttachFragment (Fragment fragment) { 
    fragList.add(new WeakReference(fragment)); 
} 

public List<Fragment> getActiveFragments() { 
    ArrayList<Fragment> ret = new ArrayList<Fragment>(); 
    for(WeakReference<Fragment> ref : fragList) { 
     Fragment f = ref.get(); 
     if(f != null) { 
      if(f.isVisible()) { 
       ret.add(f); 
      } 
     } 
    } 
    return ret; 
} 

En caso de que haya ningún método listo para leer el estado del objeto (isActive() en el ejemplo), me anular onResume y onPause a establecer un indicador (podría ser sólo una campo bool).
Eso ya es una contabilidad propia, pero aún muy limitada en mi opinión teniendo en cuenta el objetivo bastante específico que desea lograr (lista dependiente del estado).

+2

Hmm, ¿la referencia WeakReference se vuelve nula si no hay referencias al Fragmento real que se agregó a la lista en onAttachFragment? –

+2

Esto funciona muy bien para mis propósitos. PS Tengo la línea: if (f = null && f.isVisible()) { \t \t \t \t ret.add (f); \t \t \t} –

+0

No, la referencia en sí no se volverá nula, solo get() devolverá nulo si la actividad se recolectó como basura. Asignar get() a una variable f y luego verificar que null es seguro. –

2

Otra forma de hacerlo sería colocar etiquetas en los fragmentos cuando los agregue a la actividad.

Por ejemplo, si agrega dinámicamente 4 fragmentos, puede añadirlos como:

for (int i = 0; i < NUM_FRAGMENTS; i++){ 
    MyFragment fragment = new Fragment(i); 
    fragmentTransaction.add(R.id.containerId, fragment, SOME_CUSTOM_PREFIX + i).commit() 
} 

Entonces, si usted necesita para obtener todos los fragmentos más tarde, puede hacerlo:

for (int i = 0; i < NUM_FRAGMENTS; i++) { 
    String tag = SOME_CUSTOM_PREFIX + i; 
    fragmentList.add((MyFragment) fragmentManager.findFragmentByTag(tag)); 
} 
12

Si utiliza la biblioteca de compatibilidad de Android, a continuación, puede llamar oculta FragmentManager.getFragments() método:

public List<Fragment> getVisibleFragments() { 
    List<Fragment> allFragments = getSupportFragmentManager().getFragments(); 
    if (allFragments == null || allFragments.isEmpty()) { 
     return Collections.emptyList(); 
    } 

    List<Fragment> visibleFragments = new ArrayList<Fragment>(); 
    for (Fragment fragment : allFragments) { 
     if (fragment.isVisible()) { 
      visibleFragments.add(fragment); 
     } 
    } 
    return visibleFragments; 
} 
+1

No deberíamos usar este método. Está marcado con '@ hide' y no se suponía que fuera incluido con el jar de la biblioteca de soporte. No debe considerarse parte de la API exportada. –

+1

Si está utilizando la biblioteca de soporte y sabe qué hay dentro, puede llamar a los métodos que desee. Lo peor que puede pasar es que, después de cambiar a una versión más nueva de la biblioteca, obtenga errores de compilación. – Michael

+9

@ Michael Una cosa importante que me gustaría señalar para este método para los futuros espectadores (que parece que han cubierto aquí) es que devuelve la lista de fragmentos internos, y no una copia de la misma. Entonces no modifique la lista que recibe; crea una nueva lista basada en la respuesta devuelta y modifica * that * one. De lo contrario, pasará un día entero depurando una excepción intermitente IndexOutOfBoundsException. :) – kcoppock

0

I resuelto con esto:

public ArrayList<Fragment> getAllFragments() { 
    ArrayList<Fragment> lista = new ArrayList<Fragment>(); 

    for (Fragment fragment : getSupportFragmentManager().getFragments()) { 
     try { 
      fragment.getTag(); 
      lista.add(fragment); 
     } catch (NullPointerException e) { 

     } 
    } 

    return lista; 

} 
+0

Estoy implementando algo similar a esto y obtengo un NPE cada vez que lo hago. la actividad se recrea y se llama a fragment.getTag(). ¿Sabes por qué el fragmento es nulo? – Clocker

+0

Lo siento pero no. Funcionó simplemente para mí. –

1

android.support.v4.app.FragmentManager tiene un método llamado getFragments() que hace exactamente lo que necesita, pero nunca fue accesible. De repente, sin embargo, lo es, pero no estoy seguro si eso es porque todavía está marcado como oculto.

/** 
* Get a list of all fragments that have been added to the fragment manager. 
* 
* @return The list of all fragments or null if none. 
* @hide 
*/ 
public abstract List<Fragment> getFragments(); 

La regulares android.app.FragmentManager no tiene este método en absoluto, pero si realmente se necesita, se puede acceder al mismo objeto por conseguir el campo mActive través de la reflexión (tenga cuidado de no: a partir de 26 API, su tipo es a SparseArray en lugar de List). Usar bajo su propio riesgo :)

+1

El método es público, pero [tiene un error] (https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner% 20Summary% 20Stars & groupby = & sort = -id & id = 226196) –

+0

Una comprobación nula durante la iteración corrige eso. – 0101100101

+0

¡Está disponible para android.app.FragmentManager! –

Cuestiones relacionadas