Android nested fragments - java.lang.IllegalStateException: Activity has been destroyed -
Android nested fragments - java.lang.IllegalStateException: Activity has been destroyed -
i'm trying create tabbed layout using fragmenttabhost
. worked fine, realized want switch multiple fragments in single tab.
after seeing few examples of nested fragments, implemented below class should, on 1 hand, become single fragment added tab host, , on other hand parent fragment contents of tab:
/** * instances of class used containers fragments within app's tabs. * * reason using intermediate class need switch multiple fragments * in single tab. since each tab supposed hold single fragment, container * fragment. actual switching of fragments happens here , not in app's tab. */ public class fragmentcontainer extends fragment { public static final string param_content_fragment = "param_content_fragment"; public static final string extra_default_fragment = "default_fragment"; public static fragmentcontainer newinstance(string class_name) { fragmentcontainer container = new fragmentcontainer(); bundle bundle = new bundle(1); bundle.putstring(extra_default_fragment, class_name); container.setarguments(bundle); homecoming container; } @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { homecoming inflater.inflate(r.layout.fragment_container, null); } @override public void onresume() { super.onresume(); fragment f = getchildfragmentmanager().findfragmentbyid(r.id.fragment_content); if (f == null) { class<? extends fragment> claz = (class<? extends fragment>) getarguments().getserializable( param_content_fragment); fragmenttransaction tx = getchildfragmentmanager().begintransaction(); seek { f = claz.newinstance(); f.settargetfragment(this, 0); tx.add(r.id.fragment_content, f); tx.commit(); getchildfragmentmanager().executependingtransactions(); } grab (exception e) { e.printstacktrace(); throw new runtimeexception(e); } } } @override public void ondetach() { super.ondetach(); seek { field childfragmentmanager = fragment.class.getdeclaredfield("mchildfragmentmanager"); childfragmentmanager.setaccessible(true); childfragmentmanager.set(this, null); } grab (nosuchfieldexception e) { throw new runtimeexception(e); } grab (illegalaccessexception e) { throw new runtimeexception(e); } } public void replacecontent(class<? extends fragment> claz, bundle args) { fragmenttransaction tx = getchildfragmentmanager().begintransaction(); tx.settransition(fragmenttransaction.transit_fragment_open); // save fragment curfrag = getchildfragmentmanager().findfragmentbyid(r.id.fragment_content); if (curfrag != null) { tx.addtobackstack(curfrag.getclass().getsimplename()); } // alter seek { fragment newfragment = claz.newinstance(); newfragment.setarguments(args); tx.replace(r.id.fragment_content, newfragment, claz.getclass().getsimplename()); tx.commit(); getchildfragmentmanager().executependingtransactions(); } grab (exception e) { e.printstacktrace(); } } // suppress "unchecked" warning. claz variable checked compatibility fragment class // within surrounding "if" statement @suppresswarnings("unchecked") public void setdefaultcontent(bundle args) { class<?> claz = null; seek { claz = class.forname(getarguments().getstring(extra_default_fragment)); } grab (classnotfoundexception e) { e.printstacktrace(); } // ensure claz extends fragment if (claz != null && fragment.class.isassignablefrom(claz) ) { fragment childfragment = getchildfragmentmanager().findfragmentbyid(r.id.fragment_content); // replace content if showed fragment not default if (!claz.isinstance(childfragment)) { replacecontent((class<? extends fragment>) claz, args); } } else { log.e("fragmentcontainer/setdefaultcontent", "default class either null or does" + "not extend fragment"); } } }
this piece of code activity initializes tab host:
private void initializetabhost(bundle args) { mtabhost = (fragmenttabhost) findviewbyid(android.r.id.tabhost); mtabhost.setup(this, getsupportfragmentmanager(), android.r.id.tabcontent); tabinfo tabinfo = null; main.addtab(this, mtabhost, mtabhost.newtabspec(home_tab_tag).setindicator(getstring(r.string.home_tab_indicator)), (tabinfo = new tabinfo(home_tab_tag, homefragment.class, args))); mmaptabinfo.put(tabinfo.mtag, tabinfo); // default home tab this.ontabchanged(home_tab_tag); mtabhost.setontabchangedlistener(this); } private static void addtab(main activity, fragmenttabhost tabhost, tabhost.tabspec tabspec, tabinfo tabinfo) { // attach tab view mill spec tabspec.setcontent(activity.new tabfactory(activity)); string tag = tabspec.gettag(); // check see if have fragment tab, // saved state. if so, deactivate it, because our // initial state tab isn't shown. tabinfo.mfragmentcontainer = (fragmentcontainer) activity.getsupportfragmentmanager().findfragmentbytag(tag); if (tabinfo.mfragmentcontainer != null && !tabinfo.mfragmentcontainer.isdetached()) { fragmenttransaction ft = activity.getsupportfragmentmanager().begintransaction(); ft.detach(tabinfo.mfragmentcontainer); ft.commit(); activity.getsupportfragmentmanager().executependingtransactions(); } tabhost.addtab(tabspec, tabinfo.mclass, null); } @override public void ontabchanged(string tag) { tabinfo newtab = (tabinfo) this.mmaptabinfo.get(tag); if (mlasttab != newtab) { fragmenttransaction ft = this.getsupportfragmentmanager().begintransaction(); if (mlasttab != null) { if (mlasttab.mfragmentcontainer != null) { ft.detach(mlasttab.mfragmentcontainer); } } if (newtab != null) { if (newtab.mfragmentcontainer == null) { newtab.mfragmentcontainer = fragmentcontainer.newinstance(newtab.mclass.getname()); ft.add(android.r.id.tabcontent, newtab.mfragmentcontainer, newtab.mtag); } else { ft.attach(newtab.mfragmentcontainer); } newtab.mfragmentcontainer.setdefaultcontent(null); } mlasttab = newtab; ft.commit(); this.getsupportfragmentmanager().executependingtransactions(); } else { newtab.mfragmentcontainer.setdefaultcontent(null); } }
when launch app exception when tx.commit();
called within replacecontent
(it done in order show first tab's default fragment).
i missed limitation of android scheme when building construction activity->fragmenttabhost->fragmentcontainer->fragment(s)
, or, maybe, misused 1 of apis, can't find it.
any help appreciated.
finally found it: calling newtab.mfragmentcontainer.setdefaultcontent(null);
before committing add-on of newtab.mfragmentcontainer
, making sure executed. in other words, manipulating containerfragment
before added view hierarchy.
android android-fragments
Comments
Post a Comment