IllegalStateException when replacing fragment

This is a small application for testing Android 2.2 using the compatibility package. This is (wrong, of course) the way I try to replace a fragment when I get a click. I am trying to replace it with a new (different) instance of the same Fragment class. As I explain, it does not work as expected, and I need help:

public class MainFragmentActivity extends FragmentActivity { ... public void myAction(View view) { ... RightFragment newRightFrag = RightFragment.newInstance(myNewOption); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out); ft.replace(R.id.landscape_right_fragment, newRightFrag); ft.commit(); } } 

You probably saw that my mistake. In any case, let's explain a little what the application should do:

Landscape orientation:

 --------- ---------- | L | R | -> click -> | L | R2 | --------- ---------- 

In landscape orientation, activity has a view with two fragments: "leftLand" and "rightLand", and if you click the button of the "leftLand" fragment, it will change the creation of a new fragment and replace the "rightLand" fragment with another instance of the same FragamentActivity class. What distinguishes these two instances is the parameter passed to "newInstance (int)" based on the clicked button.

Portrait Orientation:

 ----- ----- | | | | | L | -> click -> | R | | | | | ----- ----- 

In portrait orientation, it simply shows the “leftPort” fragment (it has the same layout as “leftLand”), and if you click on its button, then it launches the Intent and launches the RightFragmentActivity, which displays the “rightLand” fragment

It works fine ... unless I replace the right fragment. If I do this (by clicking the button in landscape orientation), then when I subsequently changes the orientation (reloading the activity), FragmentActivity cannot be triggered due to " IllegalStateException: Fragment RightFragment did not create a view " as follows:

 D/AndroidRuntime( 1428): Shutting down VM W/dalvikvm( 1428): threadid=1: thread exiting with uncaught exception (group=0x4001d800) E/AndroidRuntime( 1428): FATAL EXCEPTION: main E/AndroidRuntime( 1428): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.agm.test/com.agm.test.MainFragmentActivity}: android.view.InflateException: Binary XML file line #13: Error inflating class fragment E/AndroidRuntime( 1428): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663) E/AndroidRuntime( 1428): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679) E/AndroidRuntime( 1428): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3815) E/AndroidRuntime( 1428): at android.app.ActivityThread.access$2400(ActivityThread.java:125) E/AndroidRuntime( 1428): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2037) E/AndroidRuntime( 1428): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime( 1428): at android.os.Looper.loop(Looper.java:123) E/AndroidRuntime( 1428): at android.app.ActivityThread.main(ActivityThread.java:4627) E/AndroidRuntime( 1428): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime( 1428): at java.lang.reflect.Method.invoke(Method.java:521) E/AndroidRuntime( 1428): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) E/AndroidRuntime( 1428): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) E/AndroidRuntime( 1428): at dalvik.system.NativeStart.main(Native Method) E/AndroidRuntime( 1428): Caused by: android.view.InflateException: Binary XML file line #13: Error inflating class fragment E/AndroidRuntime( 1428): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:582) E/AndroidRuntime( 1428): at android.view.LayoutInflater.rInflate(LayoutInflater.java:618) E/AndroidRuntime( 1428): at android.view.LayoutInflater.inflate(LayoutInflater.java:407) E/AndroidRuntime( 1428): at android.view.LayoutInflater.inflate(LayoutInflater.java:320) E/AndroidRuntime( 1428): at android.view.LayoutInflater.inflate(LayoutInflater.java:276) E/AndroidRuntime( 1428): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:198) E/AndroidRuntime( 1428): at android.app.Activity.setContentView(Activity.java:1647) E/AndroidRuntime( 1428): at com.agm.test.MainFragmentActivity.onCreate(MainFragmentActivity.java:25) E/AndroidRuntime( 1428): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) E/AndroidRuntime( 1428): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627) E/AndroidRuntime( 1428): ... 12 more E/AndroidRuntime( 1428): Caused by: java.lang.IllegalStateException: Fragment com.agm.test.RightFragment did not create a view. E/AndroidRuntime( 1428): at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:287) E/AndroidRuntime( 1428): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:558) E/AndroidRuntime( 1428): ... 21 more W/ActivityManager( 59): Force finishing activity com.agm.test/.MainFragmentActivity 

I realized that the old "RightFragment" was not destroyed after the replacement. This is probably the result of my wrong way to try to replace it.

Any help would be really appreciated.

Thanks in advance!

/ Angel Galindo Munoz

+42
android android-fragments
09 Oct '11 at
source share
2 answers

I think you may have misunderstood my comment, so I will provide a more detailed explanation here.

One problem that usually occurs when deleting or replacing fragments is trying to remove a fragment that was added to the layout through XML, and not programmatically in Java. This is not the same as inflating your own fragment layout in the onCreateView() function of the Java fragment code (this is what you seem to describe in your answer to my comment). To illustrate what I'm talking about, I will show you two ways that people try to remove / replace fragments.

This is the wrong way to do this:

XML layout:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:name="com.example.ExampleFragment" android:id="@+id/example_fragment" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent" /> </LinearLayout> 

Java:

 swapFragment() { Fragment newFragment = new ExampleFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); transaction.commit(); } 

This code will not execute as you expect. The source fragment added to the XML layout will not be deleted. This is because XML layouts are intended to describe the elements of a static layout. You can change their contents at runtime or hide them, but you cannot remove these things from the layout. This is what Diana Hackborn talked about in the discussion topic that I’ve been involved with before.

This is the right way to do this (at least in my experience):

XML layout:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- Fragment will go here eventually, but it not added in the layout --> </LinearLayout> 

Java:

 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_layout); ExampleFragment newFragment = new ExampleFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.add(R.id.fragment_container, newFragment); transaction.commit(); } 

...

 swapFragment() { Fragment newFragment = new ExampleFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); transaction.commit(); } 

This strategy does not add a fragment to the original layout. Instead, it adds it to the Java code when creating the Activity. This allows you to remove it from the layout (using remove() or replace() )

This may not solve your problem, but it is a common difficulty created by the Fragments. You can make sure that you add Fragments appropriately so that they can be deleted, and then, if this does not solve the problem, we can fix the problems.

+92
Oct 10 '11 at 19:37
source share
— -

There is another way, when you develop applications for tablets with large screens, you can inflate a different layout for each screen orientation. You just need to create two layouts and call them portrait or landscape, in onCreate just inflate xml in accordance with the orientation.

in the onClick event, simply identify the orientation with: getResources (). getConfiguration (). orientation

and make your stuff

0
Nov 19 '13 at 18:13
source share



All Articles