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?