Add Nested Fragment after Parent Fragment view is already created
android, android-fragments, nested
Solution
You can not directly load the fragment which you have declared in `FragA`. The FragmentA will be loaded first and then after you can load the FragmentB by calling the method `addFragB()` from your `fragA's` `onCreateView()` method.
Try out as below:
Remove the line `fragA.addFragB();` from your 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 to load the `FragmentB` from `FragmentA` as 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();
}
}
Problem
I am trying to create a Fragment which has a public method for adding child Fragments to itself. I've been reading through potentially similar questions but haven't found anything to help so far. I've reduced the problem down to a simple test app shown below. Once `fragA` has been added to the main layout, I call the public method `fragA.addFragB()` to get it to add an instance of FragmentClassB to itself, but this causes the test app to crash, indicating "Activity has been destroyed" (see LogCat at the end of the post). Does this mean `fragA` has been destroyed so I can't add `fragB` to it, or does it mean `fragB` has been destroyed so I can't add it to `fragA`? Or does it mean something else entirely? 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: ianhanniballake's answer and GrIsHu's later answer which expands on the same point have both been helpful in pointing out the root of the problem. However this raises a further issue. The final intention is that FragmentClassA will be part of a library. It will be used in multiple situations and the number of FragmentClassB instances will vary, or there may even be none. Hence I need to be able to trigger the addition of the child fragments to any instance of FragmentClassA from the parent activity. I've just had a look at keeping `fragA` as a class level variable in `MainActivity` and then calling `fragA.AddFragB()` in the `MainActivity`'s `onActivityCreated()` method, but it is not available to be overridden. Any thoughts?