4

I load a bunch of Child fragments dynamically inside a Parent's Fragment linearLayout (fragmentContainer), then when user clicks a button, I need to remove them all and add new ones. I don't know the exact number of fragments that will be added each time. This is my way of removing all the fragments at once

LinearLayout ll = (LinearLayout) view.findViewById(R.id.fragmentContainer);
ll.removeAllViews();

Now I can add the new ones using fragment transaction methods. This way of removing all fragments is super easy and works for me better than removing each fragment one by one using remove() But is it a good practice? How about performance? Do you recommend a better way?

Child fragments

ThanosFisherman
  • 5,626
  • 12
  • 38
  • 63
  • 1
    you should be removing fragments with fragment transactions as well, I believe. – EpicPandaForce May 30 '15 at 22:22
  • @EpicPandaForce I know but I have to go through a loop while removing them one by one right? But my way clears everything at once with just 2 lines of code. So why bother? Are there any drawbacks in my method? – ThanosFisherman May 30 '15 at 22:26
  • You said you do this and then add new fragments, why not use FragmentTransaction.replace to remove existing ones with new one? – harism May 30 '15 at 22:30
  • @harism Because I don't know the exact number of fragments that will be added each time. for example 3 fragments could be added at first then when user clicks a button 2 fragments maybe added this time. So replace what with what? – ThanosFisherman May 30 '15 at 22:36
  • Maybe I misunderstood your use case but replace, as per documentation, should remove all Fragments within same container and then call add with the Fragment given as parameter. This works for firstly added fragment, for latter ones you should use FragmentTransaction.add. – harism May 30 '15 at 22:45

4 Answers4

4

This is my way of removing all the fragments at once

No, it isn't. It is your way of removing all views from that container.

This way of removing all fragments is super easy and works for me.

It does remove any fragments. It removes views. That is why the method is named removeAllViews().

But is it a good practice?

No. For starters, when you rotate your device or undergo a configuration change, you will notice that all your "removed" fragments come back.

Do you recommend a better way?

Keep track of the outstanding fragments (e.g., using an ArrayList<Fragment>), then iterate over that list, passing each to a remove() method on a FragmentTransaction.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I use android:configChanges="orientation" in my manifest so the removed fragments never come back. But I'm mostly interested in what you said about removeAllViews() So if this method just removes the views, Are all the previously loaded fragments being kept on memory? that's not good if it's true. So the only way to achieve what I want is looping through the arraylist of fragments and removing one by one using the remove()? – ThanosFisherman May 30 '15 at 22:53
  • @ThanosF: "I use android:configChanges="orientation" in my manifest so the removed fragments never come back" -- there are many other configuration changes than that, and the fragments will come back for all of those configuration changes. "Are all the previously loaded fragments being kept on memory?" -- yes. "So the only way to achieve what I want is looping through the arraylist of fragments and removing one by one using the remove()?" -- yes. – CommonsWare May 30 '15 at 22:54
  • 1
    Also, please bear in mind that the fragment system was designed around having only one fragment in a container at a time (typically a `FrameLayout` or a subclass of that). You may experience other side effects of trying to have several fragments in one container. – CommonsWare May 30 '15 at 22:56
  • The removed fragments are never comming back no matter How I tried. Actually this is about child fragments that are being loaded inside a parent fragment. They try to simulate a listview kind of. (Each fragment represents a list Item) So you think this is not a good idea? – ThanosFisherman May 30 '15 at 23:01
  • "Actually this is about child fragments that are being loaded inside a parent fragment" -- ah. Wild horses can't get me to use nested fragments, so I am unfamiliar with the rules here regarding configuration changes. "So you think this is not a good idea?" -- I'm definitely not a fan. – CommonsWare May 30 '15 at 23:07
  • thanks I thought nested fragments and normal fragments share the same rules and principles. but apparently they don't so I have edited my question to fit more in nested fragment concept. I also checked the memory usage on android studio and it seems that no matter how many child fragments I add/remove using my noobish way the memory usage doesn't increase – ThanosFisherman May 30 '15 at 23:29
2

If you simply want to remove all fragments, code below:

FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {    
    fm.popBackStack();
}

This code is good only if you use the add method of FragmentTransaction when referencing fragments. Method popBackStack is used for removing.

The Original Android
  • 6,147
  • 3
  • 26
  • 31
1

In Kotlin you can do:

repeat(fragmentManager.backStackEntryCount) {
    fragmentManager.popBackStack()
}

Where fragmentManager could be one of:

  • Activity.supportFragmentManager
  • Fragment.requireActivity().supportFragmentManager
  • Fragment.childFragmentManager
  • Fragment.parentFragmentManager which replaced requireFragmentManager()
MatPag
  • 41,742
  • 14
  • 105
  • 114
0

I would like to suggest you: Use Kotlin and fragment-ktx using this one:

In your gradle:

implementation "androidx.fragment:fragment-ktx:$androidXFragmentKtxVersion"

In your Fragment

childFragmentManager
      .findFragmentByTag(YOUR_TAG)?.let { fragment ->
        childFragmentManager.commit(allowStateLoss = true) {
          remove(fragment)
        }
      }

If you are not using childFragmentManager use requireActivity().supportFragmentManager instead

requireActivity().supportFragmentManage
          .findFragmentByTag(YOUR_TAG)?.let { fragment ->
            requireActivity().supportFragmentManage.commit(allowStateLoss = true) {
              remove(fragment)
            }
      }
Cristofer
  • 1,046
  • 13
  • 21