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();
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?