Is there a way to get references for all currently active fragments in an Activity?

AndroidAndroid FragmentsAndroid 3.0-Honeycomb

Android Problem Overview


I haven't found a simple way to get all currently active (visible, currently in Resumed state) Fragments in an Activity. Is it possible without custom bookkeeping in my Activity? It seems that the FragmentManager doesn't support this feature.

Android Solutions


Solution 1 - Android

Looks like the API currently misses a method like "getFragments".
However using the event "onAttachFragment" of class Activity it should be quite easy to do what you want. I would do something like:

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

In case there's no ready method to read the state from the object (isActive() in the example), I would override onResume and onPause to set a flag (could be just a bool field).
That's already some own bookkeeping, but still very limited in my opinion considering the quite specific goal you want to achieve (status dependent list).

Solution 2 - Android

If you use Android Support Library, then you can call hidden FragmentManager.getFragments() method:

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

Solution 3 - Android

Another way to do this would be to put tags on your fragments when you add them to the activity.

For example, if you dynamically add 4 fragments, you can add them like:

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

Then, if you need to get all the fragments back later, you can do:

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

Solution 4 - Android

I resolved with this:

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;

}

Solution 5 - Android

android.support.v4.app.FragmentManager has a method called getFragments() which does exactly what you need, but it was never accessible. Suddenly, though, it is, but I'm not sure if that's intended because it's still marked as hidden.

/**
 * 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();

The regular android.app.FragmentManager doesn't have this method at all, but if really needed, you can access the same object by getting the field mActive via reflection (be careful there: starting with API 26, its type is a SparseArray instead of List). Use at own risk :)

Solution 6 - Android

Here is a recursive solution in Kotlin. Given the top-most fragments of an activity, returns all the descendant fragments.

fun recursiveGetFragments(parents: List<Fragment>): List<Fragment> {
    val result = parents.toMutableList()
    for(root in parents) {
        if (root.isVisible) {
            result.addAll(recursiveGetFragments(root.childFragmentManager.fragments))
        }
    }
    return result
 }

It is used as:

val fragmentList = recursiveGetFragments(supportFragmentManager.fragments)

Solution 7 - Android

we can use some irregular-but-legal method

    ArrayList<Fragment> getActiveFragments() {
        Fragment f;
        final ArrayList<Fragment> fragments = new ArrayList<>();
        int i = 0;
        try {
            while ((f = getFragmentManager().getFragment(new Intent().putExtra("anyvalue", i++).getExtras(), "anyvalue")) != null) {
                fragments.add(f);
            }
        } catch (IllegalStateException ex) {

        }
        return fragments;
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZsombor Erdődy-NagyView Question on Stackoverflow
Solution 1 - Androiddidi_X8View Answer on Stackoverflow
Solution 2 - AndroidMichaelView Answer on Stackoverflow
Solution 3 - AndroidtheelfismikeView Answer on Stackoverflow
Solution 4 - AndroidMatheus Henrique da SilvaView Answer on Stackoverflow
Solution 5 - Android0101100101View Answer on Stackoverflow
Solution 6 - AndroidKenan SoyluView Answer on Stackoverflow
Solution 7 - AndroidYessyView Answer on Stackoverflow