android - Orientation Change: IllegalStateException when DialogFragment is visible -
i'd allow android handle orientation change. unfortunately crashes each time dialog open , orientation alter occurs. suspect cause don't know how handle it:
when application first starts backstack looks this:
02-07 15:25:36.517: i/system.out(14541): added fragments: 02-07 15:25:36.517: i/system.out(14541): #0: portraitmodefragment{41963330 #0 id=0x7f090001 listviewfragment}
great, open dialog:
02-07 15:26:03.316: i/system.out(14541): added fragments: 02-07 15:26:03.316: i/system.out(14541): #0: portraitmodefragment{41963330 #0 id=0x7f090001 listviewfragment} 02-07 15:26:03.326: i/system.out(14541): #1: mydialogfragment{4199f6a0 #1 mydialogfragment}
and when rotate device:
02-07 15:26:37.502: e/androidruntime(14541): fatal exception: main 02-07 15:26:37.502: e/androidruntime(14541): java.lang.runtimeexception: unable start activity componentinfo{com.example.testapp/com.example.testapp.mainactivity}: android.view.inflateexception: binary xml file line #11: error inflating class fragment 02-07 15:26:37.502: e/androidruntime(14541): @ android.app.activitythread.performlaunchactivity(activitythread.java:2180) 02-07 15:26:37.502: e/androidruntime(14541): @ android.app.activitythread.handlelaunchactivity(activitythread.java:2230) 02-07 15:26:37.502: e/androidruntime(14541): @ android.app.activitythread.handlerelaunchactivity(activitythread.java:3692) 02-07 15:26:37.502: e/androidruntime(14541): @ android.app.activitythread.access$700(activitythread.java:141) 02-07 15:26:37.502: e/androidruntime(14541): @ android.app.activitythread$h.handlemessage(activitythread.java:1240) 02-07 15:26:37.502: e/androidruntime(14541): @ android.os.handler.dispatchmessage(handler.java:99) 02-07 15:26:37.502: e/androidruntime(14541): @ android.os.looper.loop(looper.java:137) 02-07 15:26:37.502: e/androidruntime(14541): @ android.app.activitythread.main(activitythread.java:5039) 02-07 15:26:37.502: e/androidruntime(14541): @ java.lang.reflect.method.invokenative(native method) 02-07 15:26:37.502: e/androidruntime(14541): @ java.lang.reflect.method.invoke(method.java:511) 02-07 15:26:37.502: e/androidruntime(14541): @ com.android.internal.os.zygoteinit$methodandargscaller.run(zygoteinit.java:793) 02-07 15:26:37.502: e/androidruntime(14541): @ com.android.internal.os.zygoteinit.main(zygoteinit.java:560) 02-07 15:26:37.502: e/androidruntime(14541): @ dalvik.system.nativestart.main(native method) 02-07 15:26:37.502: e/androidruntime(14541): caused by: android.view.inflateexception: binary xml file line #11: error inflating class fragment 02-07 15:26:37.502: e/androidruntime(14541): @ android.view.layoutinflater.createviewfromtag(layoutinflater.java:704) 02-07 15:26:37.502: e/androidruntime(14541): @ android.view.layoutinflater.rinflate(layoutinflater.java:746) 02-07 15:26:37.502: e/androidruntime(14541): @ android.view.layoutinflater.inflate(layoutinflater.java:489) 02-07 15:26:37.502: e/androidruntime(14541): @ android.view.layoutinflater.inflate(layoutinflater.java:396) 02-07 15:26:37.502: e/androidruntime(14541): @ android.view.layoutinflater.inflate(layoutinflater.java:352) 02-07 15:26:37.502: e/androidruntime(14541): @ com.android.internal.policy.impl.phonewindow.setcontentview(phonewindow.java:270) 02-07 15:26:37.502: e/androidruntime(14541): @ android.app.activity.setcontentview(activity.java:1881) 02-07 15:26:37.502: e/androidruntime(14541): @ com.example.testapp.mainactivity.oncreate(mainactivity.java:17) 02-07 15:26:37.502: e/androidruntime(14541): @ android.app.activity.performcreate(activity.java:5104) 02-07 15:26:37.502: e/androidruntime(14541): @ android.app.instrumentation.callactivityoncreate(instrumentation.java:1080) 02-07 15:26:37.502: e/androidruntime(14541): @ android.app.activitythread.performlaunchactivity(activitythread.java:2144) 02-07 15:26:37.502: e/androidruntime(14541): ... 12 more 02-07 15:26:37.502: e/androidruntime(14541): caused by: java.lang.illegalstateexception: fragment com.example.testapp.fragments.landscapemodefragment did not create view. 02-07 15:26:37.502: e/androidruntime(14541): @ android.support.v4.app.fragmentactivity.oncreateview(fragmentactivity.java:303) 02-07 15:26:37.502: e/androidruntime(14541): @ android.view.layoutinflater.createviewfromtag(layoutinflater.java:676)
interesting fun-fact: not happen if first turn around device , subsequently open dialog , alter orientation, because both fragments preloaded , exist peacefully in backstack:
02-07 15:34:00.015: i/system.out(15412): #0: portraitmoderagment{419b99b0 #0 id=0x7f090001 listviewfragment} 02-07 15:34:00.015: i/system.out(15412): #1: landscapemodefragment{419b9b88 #1 id=0x7f090003 landscapemodefragment} 02-07 15:34:00.025: i/system.out(15412): #2: mydialogfragment{419d1da0 #2 mydialogfragment}
i cant create user rotate smartphone around before using app, do? ;)
to reproduce:
how add together dialog backstack:
mydialogfragment mytvshowdialog = new mydialogfragment(); mytvshowdialog.show(getactivity().getsupportfragmentmanager(),mytvshowdialog.tag);
what did create 2 xml files mainactivity:
1 . res/layout/main.xml (portraitmode):
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <textview android:id="@+id/textview1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="layout-land/portrait" /> <fragment class="com.example.testapp.fragments.portraitmodefragment" android:id="@+id/fragment" android:layout_weight="1" android:layout_width="0px" android:layout_height="match_parent" android:tag="portraitmodefragment"> </fragment> </linearlayout>
2 . res/layout-land/main.xml (landscapemode)
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <textview android:id="@+id/textview1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="layout-land/landscape" /> <fragment class="com.example.testapp.fragments.landscapemodefragment" android:id="@+id/landscapemodefragment" android:layout_weight="1" android:layout_width="0px" android:layout_height="0dp" android:tag="landscapemodefragment"> </fragment> </linearlayout>
mainactivity.java:
public class mainactivity extends fragmentactivity { private static final string tag = "mainactivity"; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); log.v(tag, "oncreate()"); setcontentview(r.layout.activity_main); getsupportfragmentmanager().dump("", null, new printwriter(system.out, true), null); } }
fragmentportraitmode:
public class portraitmodefragment extends fragment { @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view fragment = inflater.inflate(r.layout.portraitmodefragment_layout, null); button findviewbyid = (button) fragment.findviewbyid(r.id.button1); findviewbyid.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { mydialogfragment mydialog = new mydialogfragment(); mydialog.show(getactivity().getsupportfragmentmanager(), mydialogfragment.tag); } }); textview textview = (textview) fragment.findviewbyid(r.id.textview1); textview.settext(tag); homecoming fragment; }
fragment landscapemode:
public class landscapemodefragment extends fragment { public static final string tag = "landscapemodefragment"; @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view fragment = inflater.inflate(r.layout.landscapemode_fragment_layout, container, false); homecoming fragment; } }
landscapemode_fragment_layout.xml:
<?xml version="1.0" encoding="utf-8"?> <linearlayout 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"> <textview android:id="@+id/textview1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="landscapefragment" /> </linearlayout>
portraitmode_fragment_layout_xml:
<?xml version="1.0" encoding="utf-8"?> <linearlayout 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"> <button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button" /> <textview android:id="@+id/textview1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="textview" /> </linearlayout>
well i've found workaround works fine.
first: problem?
fragments defined in layout-xml , fragments added per fragmentmanager have different lifecycles abd though possible mess layout-fragments fragmentmanager unexpected behaviour (exceptions) causes application crash.
as dianne hackborn mentioned in google groups forum
defining fragments in xml intended things going remain around. if going add together , remove, should consistently dynamically.
i can future release, please note whatever can bad situations using -- illustration if don't have unique containing view grouping fragment, happens remove/add fragments @ point in hierarchy going behave inconsistently.
so not allowed mix worlds (fragmentmanager-fragments , layoutxml-fragments). unfortunately involves dialogfragments added @ runtime too. happens: android-framework adds on orientation-change newly layout-created fragment backstack. fragmentmanager trys add together dialogfragment afterwards on same index newly created layout-fragment. thats when things messy , illegalstateexception occurs.
so, whats workaround?
most examples using fragments different orientations involve defining framelayout container, set right fragment it. we'll go way fragmentmanager , bann layoutfragments our design:
activitymain uses simple xml contentview:
<?xml version="1.0" encoding="utf-8"?> <framelayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_container_id" android:layout_width="fill_parent" android:layout_height="fill_parent"> </framelayout>
and when started injects right fragment container
/** called when activity first created. */ @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.mainactivity_framelayout); createfragmentifnotexits(); } private void createfragmentifnotexits() { int orientation = getresources().getconfiguration().orientation; fragment newfragment; if (orientation == configuration.orientation_portrait) { newfragment = new tvshowlistportraitmodefragment(); } else { newfragment = new tvshowlistlandscapemodefragment(); } fragmenttransaction ft = getsupportfragmentmanager().begintransaction(); ft.replace(r.id.fragment_container_id, newfragment); ft.commit(); }
the drawback: unfortunately retaining saved state of fragments not possible way. or @ to the lowest degree still need figure our how this.
so much me. not mark reply "answered" since did not create work, maybe figure out , post simpler solution. mark ofcourse correct.
android android-orientation android-dialogfragment
No comments:
Post a Comment