Adding a nested fragment after viewing the parent fragment

I am trying to create a fragment that has a public method of adding child fragments to itself.

I read potentially similar questions, but so far have not found anything to help. I reduced the problem to a simple test application, shown below.

Once fragA been added to the main layout, I call the public fragA.addFragB() method so that it can add an instance of FragmentClassB to itself, but this leads to a crash of the test application, indicating that the “Activity was destroyed” (see LogCat at the end of the message). Does this mean that fragA was destroyed, so I can’t add fragB to it, or does it mean that fragB was destroyed, so I can’t add it to fragA ? Or does it mean something else?

MainActivity.java

 public class MainActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FragmentManager fragMan = getSupportFragmentManager(); // add Fragment A to the main linear layout FragmentTransaction fragTrans = fragMan.beginTransaction(); FragmentClassA fragA = new FragmentClassA(); fragTrans.add(R.id.mainLinearLayout, fragA); fragTrans.addToBackStack("A"); fragTrans.commit(); // get Fragment A to add a Fragment B to itself fragA.addFragB(); } } 

activity_main.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <LinearLayout android:id="@+id/mainLinearLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:orientation="horizontal" > </LinearLayout> </RelativeLayout> 

FragmentClassA.java

 public class FragmentClassA extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_a, container, false); } public void addFragB() { FragmentManager childFragMan = getChildFragmentManager(); FragmentTransaction childFragTrans = childFragMan.beginTransaction(); FragmentClassB fragB = new FragmentClassB(); childFragTrans.add(R.id.fragA_LinearLayout, fragB); childFragTrans.addToBackStack("B"); childFragTrans.commit(); } } 

fragment_a.xml

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragA_LinearLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > </LinearLayout> 

FragmentClassB.java

 public class FragmentClassB extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_b, container, false); } } 

fragment_b.xml

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" /> </LinearLayout> 

Logcat

 11-18 16:17:05.627: E/AndroidRuntime(14351): FATAL EXCEPTION: main 11-18 16:17:05.627: E/AndroidRuntime(14351): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.nestedfragmenttest/com.example.nestedfragmenttest.MainActivity}: java.lang.IllegalStateException: Activity has been destroyed 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211) 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261) 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.app.ActivityThread.access$600(ActivityThread.java:141) 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256) 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.os.Handler.dispatchMessage(Handler.java:99) 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.os.Looper.loop(Looper.java:137) 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.app.ActivityThread.main(ActivityThread.java:5103) 11-18 16:17:05.627: E/AndroidRuntime(14351): at java.lang.reflect.Method.invokeNative(Native Method) 11-18 16:17:05.627: E/AndroidRuntime(14351): at java.lang.reflect.Method.invoke(Method.java:525) 11-18 16:17:05.627: E/AndroidRuntime(14351): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 11-18 16:17:05.627: E/AndroidRuntime(14351): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 11-18 16:17:05.627: E/AndroidRuntime(14351): at dalvik.system.NativeStart.main(Native Method) 11-18 16:17:05.627: E/AndroidRuntime(14351): Caused by: java.lang.IllegalStateException: Activity has been destroyed 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1365) 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595) 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574) 11-18 16:17:05.627: E/AndroidRuntime(14351): at com.example.nestedfragmenttest.FragmentClassA.addFragB(FragmentClassA.java:26) 11-18 16:17:05.627: E/AndroidRuntime(14351): at com.example.nestedfragmenttest.MainActivity.onCreate(MainActivity.java:25) 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.app.Activity.performCreate(Activity.java:5133) 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 11-18 16:17:05.627: E/AndroidRuntime(14351): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175) 11-18 16:17:05.627: E/AndroidRuntime(14351): ... 11 more 

EDIT:

The ianhanniballake answer and the later GrIsHu answer, which expands at the same point, were both helpful, indicating the root of the problem. However, this causes an additional problem.
The final intention is that FragmentClassA will be part of the library. It will be used in several situations, and the number of instances of FragmentClassB will vary, or they may not even be. Therefore, I need to be able to initiate the addition of child fragments to any instance of FragmentClassA from the parent activity. I just looked at saving fragA as a class level variable in MainActivity , and then calling fragA.addFragB() in the MainActivity onActivityCreated() method, but it is not overrideable. Any thoughts?

+7
android nested android-fragments
source share
3 answers

You cannot directly download the fragment that you specified in FragA . First FragmentA is loaded, and then after loading FragmentB the addFragB() method is addFragB() from your fragA's onCreateView() method.

Try the following:

Delete the line fragA.addFragB(); from MainActivity

 public class MainActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FragmentManager fragMan = getSupportFragmentManager(); // add Fragment A to the main linear layout FragmentTransaction fragTrans = fragMan.beginTransaction(); FragmentClassA fragA = new FragmentClassA(); fragTrans.add(R.id.mainLinearLayout, fragA); fragTrans.addToBackStack("A"); fragTrans.commit(); } } 

And try loading FragmentB from FragmentA as shown below:

 public class FragmentClassA extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { addFragB(); //Call and load fragment B here. return inflater.inflate(R.layout.fragment_a, container, false); } public void addFragB() { FragmentManager childFragMan = getChildFragmentManager(); FragmentTransaction childFragTrans = childFragMan.beginTransaction(); FragmentClassB fragB = new FragmentClassB(); childFragTrans.add(R.id.fragA_LinearLayout, fragB); childFragTrans.addToBackStack("B"); childFragTrans.commit(); } } 
+7
source share

FragmentTransaction.commit not an immediate documentation action, so your fragA not attached to an Activity (hence why it returns that the action is destroyed) when you call fragA.addFragB() .

Instead of addFragB() you should call FragmentClassA.onCreate() to make sure fragA attached to the action and ready to initialize its own state.

+2
source share

You tried to add this to child fragments:

 @Override public void onDetach() { super.onDetach(); try { Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager"); childFragmentManager.setAccessible(true); childFragmentManager.set(this, null); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } 

this avoids runtime problems when switching between different fragments.

Say you have activity with a fragment, which in turn has two child fragments: fragA and FragB .

You can implement child fragments something like this:

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.activity_mymessages, container, false); FragmentManager manager = getChildFragmentManager(); FragmentTransaction ft = manager.beginTransaction(); ft.replace(R.id.headlines, fragA); ft.replace(R.id.article, fragB); ft.commit(); return root; } 

activity_mymessages.xml

 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal"> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal"> <FrameLayout android:id="@+id/headlines" android:layout_height="match_parent" android:name="com.example.fragA" android:layout_width="103dp" android:layout_marginRight="10dp"/> <FrameLayout android:id="@+id/article" android:layout_height="fill_parent" android:name="com.example.fragB" android:layout_width="fill_parent" /> </LinearLayout> </FrameLayout> 

Let me know if this works, if not, I can provide working code from my GitHub.

0
source share

All Articles