android - OutOfMemoryError if I restart a finished activity with ViewPager -



android - OutOfMemoryError if I restart a finished activity with ViewPager -

i worked on issue cannot find solution expect unnatural way http://stackoverflow.com/a/2866717/2008040

i have activity (webviewactivityforheadlines) started main activity, activity contains custom view pager (same behavior happens when utilize standard view pager) , view pager inflates custom zoomable image views (same behavior happens when utilize standard image view).

you can find code of activity below, cutting out unrelated parts.

@fullscreen @eactivity(r.layout.activity_web_view_for_headlines) public class webviewactivityforheadlines extends baseactivity { /** log tag. */ private static final string log_tag = webviewactivityforheadlines.class.getsimplename(); private static int num_pages; private static string current_url = ""; private static string current_title = ""; headlinelistadapter headlinelistadapter = gazetelikapplication.headlinelistadapter; @viewbyid(r.id.mpager) public static jazzyviewpager mpager; pageradapter mpageradapter; @bean gazeteliksharinghelper gazeteliksharinghelper; @viewbyid button webviewbuttonback; @viewbyid button webviewbuttonforward; @viewbyid button webviewbuttonhome; @viewbyid button webviewbuttonhide; @viewbyid button webviewbuttonshare; @viewbyid button webviewbuttonclose; @viewbyid(r.id.webviewcontrolpanel) relativelayout controlpanel; @viewbyid(r.id.upperlayout) relativelayout upperlayout; @viewbyid(r.id.mainrelativelayout) relativelayout mainlayout; @viewbyid(r.id.webviewshowcontrolpanelpanel) relativelayout showcontrolpanelpanel; boolean isfirstrun = true; integer orderidofstart = null; string tinyurlstring = ""; boolean istinyurlready; int tinyurlcount; // progressdialog mprogressdialog; /** view show ad. */ private adview adview; final activity thisactivity = this; displayimageoptions options; resources res; @suppresslint("newapi") @afterviews void afterviews() { num_pages = headlinelistadapter.getcount(); intent thisintent = getintent(); // gets created intent orderidofstart = thisintent.getintextra("orderid", 0); mpageradapter = new imageadapter(); mpager.setadapter(mpageradapter); mpager.setcurrentitem(orderidofstart); mpager.settransitioneffect(jazzyviewpager.transitioneffect.accordion); view decorview = getwindow().getdecorview(); if (build.version.sdk_int == 14 || build.version.sdk_int == 15) { int uioptions = view.system_ui_flag_hide_navigation; decorview.setsystemuivisibility(uioptions); } else if (build.version.sdk_int >= 16) { if (build.version.sdk_int >= 19) { int uioptions = view.system_ui_flag_hide_navigation | view.system_ui_flag_fullscreen | view.system_ui_flag_immersive_sticky; decorview.setsystemuivisibility(uioptions); gettemporarycache().setwebviewcontrolpanelvisible(true); } else { int uioptions = view.system_ui_flag_hide_navigation | view.system_ui_flag_fullscreen; decorview.setsystemuivisibility(uioptions); } } res = getresources(); displayimageoptions options = new displayimageoptions.builder() .showimageonloading(r.drawable.ic_launcher) .showimageforemptyuri(r.drawable.ic_launcher) .cacheinmemory(false) .build(); } /** called before activity destroyed. */ @override public void ondestroy() { seek { upperlayout.removeallviews(); mainlayout.removeallviews(); mpageradapter = null; mpager.removeallviews(); } grab (exception e) { toast.maketext(thisactivity, e.getlocalizedmessage(), toast.length_short).show(); } super.ondestroy(); } @click(r.id.webviewbuttonback) void onbuttonbackclick() { int desiredpage = mpager.getcurrentitem() - 1; if (desiredpage < 0) { desiredpage = 0; } if (desiredpage > mpageradapter.getcount()) { desiredpage = mpageradapter.getcount(); } mpager.setcurrentitem(desiredpage); } @click(r.id.webviewbuttonforward) void onbuttonforwardclick() { int desiredpage = mpager.getcurrentitem() + 1; if (desiredpage < 0) { desiredpage = 0; } if (desiredpage > mpageradapter.getcount()) { desiredpage = mpageradapter.getcount(); } mpager.setcurrentitem(desiredpage); } @click(r.id.webviewbuttonhome) void onbuttonhomeclick() { mpager.setcurrentitem(orderidofstart); } @click(r.id.webviewbuttonhide) void onbuttonhideclick() { upperlayout.removeview(controlpanel); showcontrolpanelpanel.setvisibility(relativelayout.visible); } @click(r.id.webviewbuttonclose) void onbuttoncloseclick() { finish(); } @click(r.id.webviewbuttonshare) void onbuttonshareclick() { ... } @background void buildtinyurl(string longurl) { ... } @uithread void onothersharebuttonclicktask(string url) { ... } @uithread void onfacebooksharebuttonclicktask(string url) { ... } @uithread void ontwittersharebuttonclicktask(string url) { ... } @click(r.id.webviewbuttonshow) void onbuttonshowclick() { upperlayout.addview(controlpanel); showcontrolpanelpanel.setvisibility(relativelayout.invisible); } @uithread void popuptoast(string message) { if (message != null) { toast.maketext(this, message, toast.length_long).show(); } } @override public void onconfigurationchanged(configuration newconfig) { relativelayout layout = (relativelayout) findviewbyid(r.id.headlinesforaddrelativelayout); layout.removeview(adview); if (adview != null) { // destroy adview. adview.destroy(); } super.onconfigurationchanged(newconfig); } @override public void onbackpressed() { if (orderidofstart == mpager.getcurrentitem()) { super.onbackpressed(); } else if (mpager.getcurrentitem() > orderidofstart) { mpager.setcurrentitem(mpager.getcurrentitem() - 1); } else if (mpager.getcurrentitem() < orderidofstart) { mpager.setcurrentitem(mpager.getcurrentitem() + 1); } } private class imageadapter extends pageradapter { private layoutinflater inflater; imageadapter() { inflater = layoutinflater.from(thisactivity); } @override public void destroyitem(viewgroup container, int position, object object) { container.removeview((view) object); } @override public int getcount() { homecoming num_pages; } @override public object instantiateitem(viewgroup view, int position) { view imagelayout = inflater.inflate(r.layout.simple_image_view, view, false); assert imagelayout != null; final touchimageview imageview = (touchimageview) imagelayout.findviewbyid(r.id.image); final progressbar spinner = (progressbar) imagelayout.findviewbyid(r.id.loading); imageloader.getinstance().displayimage(headlinelistadapter.getitem(position).geturl(), imageview, options, new simpleimageloadinglistener() { @override public void onloadingstarted(string imageuri, view view) { spinner.setvisibility(view.visible); } @override public void onloadingfailed(string imageuri, view view, failreason failreason) { string message = null; switch (failreason.gettype()) { case io_error: message = "input/output error"; break; case decoding_error: message = "image can't decoded"; break; case network_denied: message = "downloads denied"; break; case out_of_memory: message = "out of memory error"; break; case unknown: message = "unknown error"; break; } toast.maketext(thisactivity, message, toast.length_short).show(); spinner.setvisibility(view.gone); } @override public void onloadingcomplete(string imageuri, view view, bitmap loadedimage) { spinner.setvisibility(view.gone); imageview.setzoom(1f); } }); view.addview(imagelayout, 0); homecoming imagelayout; } @override public boolean isviewfromobject(view view, object object) { homecoming view.equals(object); } @override public void restorestate(parcelable state, classloader loader) { } @override public parcelable savestate() { homecoming null; } } }

when start activity first time, can see heap go little view pager inflates 3 views , things ok when navigate between tens of images. see when finish activity memory not released scheme , if start activity 1 time again , 1 time again oome expected.

this logcat output

java.lang.outofmemoryerror @ android.graphics.bitmapfactory.nativedecodestream(native method) @ android.graphics.bitmapfactory.decodestream(bitmapfactory.java:623) @ com.nostra13.universalimageloader.core.decode.baseimagedecoder.decode(baseimagedecoder.java:78) @ com.nostra13.universalimageloader.core.loadanddisplayimagetask.decodeimage(loadanddisplayimagetask.java:264) @ com.nostra13.universalimageloader.core.loadanddisplayimagetask.tryloadbitmap(loadanddisplayimagetask.java:237) @ com.nostra13.universalimageloader.core.loadanddisplayimagetask.run(loadanddisplayimagetask.java:135) @ java.util.concurrent.threadpoolexecutor.runworker(threadpoolexecutor.java:1080) @ java.util.concurrent.threadpoolexecutor$worker.run(threadpoolexecutor.java:573) @ java.lang.thread.run(thread.java:856)

could guys please help me find out memory leak?

the fact heap not cut down when finishing activity suggests gc cannot dispose of it. typical culprit persistent object still holding reference it.

i suggest review have ensure activity context isn't beingness held on outside of lifecycle. consider, instance, next problem application:

imageloader created within activity an image starts loading in background process so long background process running, reference exists activity, because task references instance of simpleimageloadinglistener created within activity instance in meantime, finish activity the activity not gc'd, because imageloader referencing simpleimageloadinglistener, references activity starting new activity exceeds heap size , causes oome

a possible solution have singleton simpleimageloadinglistener, connect when activity created.

i hope provides insight problem!

android android-viewpager android-lifecycle android-memory

Comments

Popular posts from this blog

c - Compilation of a code: unkown type name string -

java - Bypassing "final local variable defined in an enclosing type" -

json - Hibernate and Jackson (java.lang.IllegalStateException: Cannot call sendError() after the response has been committed) -