Tuesday, 15 April 2014

android - Why does my Java object reference an old activity after orientation change? -



android - Why does my Java object reference an old activity after orientation change? -

background:

i have fragmentactivity uses drawerlayout. created class called navdrawermanager abstract out code dealing drawer layout. build object, need pass in , maintain reference activity. utilize activity reference phone call findviewbyid(), , utilize activity context when creating list adapter, etc. maintain reference navdrawermanager object in activity can perform callbacks , operations on drawer layout.

update: per xaver's suggestion, switched extend fragmentactivity navdraweractivity. instead of having navdrawermanager object in activity, superclass handles nav drawer code. see updated code.

issue:

everything works fine until alter orientations. after changing orientations, appears navdraweractivity still references old layout. because have progress bar , couple of buttons in drawerlayout attempting update, don't reflect updates.

when phone call activity.findviewbyid() progress bar , create visible, doesn't show changes, nor of changes buttons show. note: activity.findviewbyid() not homecoming null. however, if same things before changing orientation, progress bar , buttons show appropriate changes.

code:

navdraweractivity:

public class navdraweractivity extends lowprofilefragmentactivity { private drawerlayout mdrawerlayout; private actionbardrawertoggle mdrawertoggle; private expandablelistview mdrawerlist; private navdraweradapter mlistadapter; @override protected void onpostcreate(bundle savedinstancestate) { super.onpostcreate(savedinstancestate); mdrawertoggle.syncstate(); } @override public boolean onoptionsitemselected(menuitem item) { mdrawertoggle.onoptionsitemselected(item); homecoming super.onoptionsitemselected(item); } //called via subclass after setcontentview protected void setupnavdrawer() { initdrawerlayout(); initdrawerlist(); setbutton1(); setbutton2(); } private void initdrawerlayout() { mdrawerlayout = (drawerlayout) findviewbyid(r.id.drawer_layout); mdrawertoggle = getactionbardrawertoggle(); mdrawerlayout.setdrawerlistener(mdrawertoggle); } private void initdrawerlist() { mdrawerlist = (expandablelistview) mdrawerlayout .findviewbyid(android.r.id.list); mlistadapter = getnavdraweradapter(); } private actionbardrawertoggle getactionbardrawertoggle() { homecoming new actionbardrawertoggle(this, mdrawerlayout, r.drawable.ic_navigation_drawer, 0, 0) { public void ondrawerclosed(view view) { } public void ondraweropened(view view) { } }; } public void setdrawerloading(boolean loading) { progressbar progressbar = (progressbar) mdrawerlayout .findviewbyid(r.id.progress_bar); button button1 = (button) this.findviewbyid(r.id.button1); button button2 = (button) .findviewbyid(r.id.button2); /* none of below changes appear after changing orientation */ if (loading) { button1.setenabled(false); button2.setenabled(false); progressbar.setvisibility(view.visible); } else { progressbar.setvisibility(view.gone); button1.setenabled(true); button2.setenabled(true); } } private void setbutton1() { button button1 = (button) this.findviewbyid(r.id.button1); button1.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { //do } }); } private void setbutton2() { button button2 = (button) .findviewbyid(r.id.button2); button2.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { //do } }); } }

exampleactivity:

public class exampleactivity extends navdraweractivity { @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); initui(); } private void initui() { setcontentview(r.layout.activity_sift); // phone call superclass method set nav drawer setupnavdrawer(); } }

androidmanifest.xml:

<activity android:name="com.example.app.exampleactivity" android:label="@string/app_name" android:launchmode="singletop" android:theme="@style/apptheme" > <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity>

wouldn't easier if implemented navdraweractivity instead of navdrawermanager? things should avoided. ui should handled solely fragments or activities themselves.

i understand why want create such navdrawermanager, create whole thing reusable , lot of abstraction great, when overdone can become problem. don't focus much on beingness abstracted , according oop standards. there nil wrong activity having both navigationdrawer , hiding notification bar. , if have activity implements 1 of 2 things should extend it. other alternative reimplement same behaviour in sec activity , pretty much defeat purpose of abstraction.

edit: have refactored , improved code, should not have many different methods everything, setup belongs in oncreate(), write methods each step introduces possibility additional errors. seek this:

public abstract class navdraweractivity extends lowprofilefragmentactivity { private actionbardrawertoggle drawertoggle; private drawerlayout drawerlayout; private progressbar progressbar; private button button1; private button button2; private expandablelistview drawerlist; private navdraweradapter drawerlistadapter; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(getlayout()); this.drawerlayout = (drawerlayout) findviewbyid(r.id.drawer_layout); this.drawertoggle = new actionbardrawertoggle(this, this.drawerlayout, r.drawable.icon_drawer, r.string.drawer_open, r.string.drawer_close); this.drawerlayout.setdrawerlistener(this.drawertoggle); this.drawerlist = (expandablelistview) this.drawerlayout.findviewbyid(android.r.id.list); this.progressbar = (progressbar) this.drawerlayout.findviewbyid(r.id.progress_bar); this.button1 = (button) findviewbyid(r.id.button1); this.button1.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { //do } }); this.button2 = (button) findviewbyid(r.id.button2); this.button2.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { //do } }); this.drawerlistadapter = new navdraweradapter(...); this.drawerlist.setadapter(this.drawerlistadapter); } protected abstract int getlayout(); @override protected void onpostcreate(bundle savedinstancestate) { super.onpostcreate(savedinstancestate); this.drawertoggle.syncstate(); } @override public void onconfigurationchanged(configuration newconfig) { super.onconfigurationchanged(newconfig); this.drawertoggle.onconfigurationchanged(newconfig); } @override public boolean onoptionsitemselected(menuitem item) { homecoming this.drawertoggle.onoptionsitemselected(item) || super.onoptionsitemselected(item); } public void setdrawerloading(boolean loading) { this.button1.setenabled(!loading); this.button2.setenabled(!loading); this.progressbar.setvisibility(loading ? view.visible : view.gone); } }

as can see utilize abstract method called getlayout() pass right layout setcontentview(). getlayout() has implemented activities extend navdraweractivity therfore giving sub activities command on used layout.

as such exampleactivity should this:

public class exampleactivity extends navdraweractivity { @override protected int getlayout() { homecoming r.layout.activity_sift; } }

i tested , it's working me.

android android-activity android-orientation android-context android-side-navigation

No comments:

Post a Comment