Memory Leak on Android Wear with fragments and ViewPager -
i have app has 1 main activity. activity holds reference fragmentmanager, , fragments use in app. once main activity loads, displays "navigation fragment", fragment holds viewpager uses fragments display menu items (done using fragmentpageradapter). when select menu item (by clicking it, or using gesture) current navigation fragment replaced menu item fragment using:
public void replacefragment(fragment frag, string fragtag) { fragment currentfrag = mfragmentmanager.findfragmentbyid(r.id.fragmentcontainer); mfragmentmanager.begintransaction() .remove(currentfrag) .add(r.id.fragmentcontainer, frag, fragtag) .addtobackstack(null) .commit(); }
when return menu item fragment navigation fragment, using:
fragmentmanager.popbackstackimmediate();
i getting big jumps in allocated memory. after selecting menu item , returning navigation fragment 8-10 times or so, memory begins fill , sensorlisteners stop working can't use gestures. i've tried re-using fragments as possible , keeping oncreateview() method of each fragment free instantiations.
this memory monitor outputs when select menu item fragment , return navigation fragment several times:
does know might causing this?
here's navigation fragment 'mainfragment':
public class mainfragment extends fragment { private mainwearactivity mmainwearactivity; view view; private int currentpage; private viewpager pager; private viewpageradapter adapter; private wearyflick myflick; private wearxflick mxflick; private vibrator vibrator; private onshakelistener yflicklistener; private onshakelistener xflicklistener; @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); mmainwearactivity = (mainwearactivity) getactivity(); vibrator = mmainwearactivity.getvibrator(); adapter = new viewpageradapter((mainwearactivity)getactivity(),getchildfragmentmanager()); myflick = new wearyflick(); mxflick = new wearxflick(); yflicklistener = new onshakelistener() { @override public void onshake() { yflickdetected(); } }; xflicklistener = new onshakelistener() { @override public void onshake() { xflickdetected(); } }; } @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view = inflater.inflate(r.layout.fragment_main, container, false); // scrolling menu pager = (viewpager) view.findviewbyid(r.id.watchnavpager); pager.setadapter(adapter); pager.addonpagechangelistener(adapter); // set current item middle page pager.setcurrentitem(consts.first_page); currentpage = consts.first_page; // set number of pages pager.setoffscreenpagelimit(4); // set no margin other pages hidden pager.setpagemargin(0); // set listeners , start listening myflick.setonshakelistener(yflicklistener); mxflick.setonshakelistener(xflicklistener); return view; } @override public void onpause() { log.d("frag", "mainfragment onpause() called"); stoplistening(); super.onpause(); } @override public void onresume() { super.onresume(); log.d("frag", "mainfragment onresume() called"); startlistening(); } private void startlistening(){ mmainwearactivity.registerlistener(myflick, consts.gyro); mmainwearactivity.registerlistener(mxflick, consts.gyro); } private void stoplistening(){ mmainwearactivity.unregisterlistener(myflick); mmainwearactivity.unregisterlistener(mxflick); } private void yflickdetected(){ vibrator.vibrate(consts.vibpattern, -1); currentpage = pager.getcurrentitem(); currentpage++; pager.setcurrentitem(currentpage, true); } private void xflickdetected(){ vibrator.vibrate(consts.vibpattern, -1); // select current menu item switch (mmainwearactivity.getcurrentselection()) { case consts.menu_item: mmainwearactivity.replacefragment(mmainwearactivity.getfragment(consts.frag_item), consts.frag_item); break; } } @override public void ondestroyview() { pager = null; super.ondestroyview(); } }
and here menu item fragment:
public class voicefragment extends fragment { private view view; private mainwearactivity mmainwearactivity; private vibrator vibrator; private fragmentmanager fmanager; private wearyshake myshake; private wearyflick myflick; private textview menuitemtext; private imageview mainimageview; private colorstatelist defaulttextcolor; private onshakelistener yflicklistener; private onshakelistener yshakelistener; private view.onclicklistener imgclicklistener; @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); mmainwearactivity = (mainwearactivity) getactivity(); vibrator = mmainwearactivity.getvibrator(); fmanager = mmainwearactivity.getfragmanager(); myshake = new wearyshake(); myflick = new wearyflick(); yflicklistener = new onshakelistener() { @override public void onshake() { yflickdetected(); } }; yshakelistener = new onshakelistener() { @override public void onshake() { yshakedetected(); } }; imgclicklistener = new view.onclicklistener() { @override public void onclick(view v) { yflickdetected(); } }; } @nullable @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { view = inflater.inflate(r.layout.fragment_menu_item, container, false); menuitemtext = (textview) view.findviewbyid(r.id.menuitemfragtxt); mainimageview= (imageview) view.findviewbyid(r.id.itemmainimg); myflick.setonshakelistener(yflicklistener); myshake.setonshakelistener(yshakelistener); mainimageview.setonclicklistener(imgclicklistener); return view; } private void promptspeechinput(){ intent intent = new intent(recognizerintent.action_recognize_speech); intent.putextra(recognizerintent.extra_language_model, recognizerintent.language_model_free_form); intent.putextra(recognizerintent.extra_language, locale.getdefault()); intent.putextra(recognizerintent.extra_prompt, consts.prompt_speech); try { startactivityforresult(intent, consts.req_code_speech_input); } catch (activitynotfoundexception a) { toast.maketext(getactivity(), consts.voice_error_msg, toast.length_short).show(); } } @override public void onactivityresult(int requestcode, int resultcode, intent data) { super.onactivityresult(requestcode, resultcode, data); switch (requestcode) { case consts.req_code_speech_input: { if (resultcode == activity.result_ok && null != data) { arraylist<string> result = data .getstringarraylistextra(recognizerintent.extra_results); menuitemtext.settext(result.get(0)); } break; } } } @override public void onpause() { log.d("frag", "itemfragment onpause() called"); stoplistening(); super.onpause(); } @override public void onresume() { super.onresume(); log.d("frag", "itemfragment onresume() called"); startlistening(); } private void startlistening(){ mmainwearactivity.registerlistener(myflick, consts.gyro); mmainwearactivity.registerlistener(myshake, consts.accel); } private void stoplistening(){ mmainwearactivity.unregisterlistener(myflick); mmainwearactivity.unregisterlistener(myshake); } private void yflickdetected(){ vibrator.vibrate(consts.vibpattern, -1); fmanager.popbackstackimmediate(); } private void yshakedetected(){ vibrator.vibrate(consts.vibpattern, -1); promptspeechinput(); } }
my viewpageradapter looks this:
public class viewpageradapter extends fragmentpageradapter implements viewpager.onpagechangelistener { private mainwearactivity context; private fragmentmanager fm; public viewpageradapter(mainwearactivity context, fragmentmanager fm) { super(fm); this.fm = fm; this.context = context; } @override public fragment getitem(int position) { position = position % consts.pages; switch(position){ case consts.item1_pos: return new adapteritem1fragment(); case consts.item2_pos: return new adapteritem2fragment(); case consts.item3_pos: return new adapteritem3fragment(); case consts.item4_pos: return new adapteritem4fragment(); default: return null; } } @override public int getcount() { return consts.pages * consts.loops; } @override public void onpagescrolled(int position, float positionoffset, int positionoffsetpixels) {} @override public void onpageselected(int position) {} @override public void onpagescrollstatechanged(int state) {} }
can see why switching between main navigation fragment , menu item fragment might causing such big jumps in memory allocation , stopping sensors working? thanks.
Comments
Post a Comment