android - Will Looping a Runnable Cause a Memory Leak -


hi have large memory leak in app , think it's being caused runnables. here example of skeleton of runnables use:

    private runnable randomalienfire = new runnable() {        public void run() {             /*a bunch                of computations             */              mainhandler.removecallbacks(randomalienfire);             mainhandler.postdelayed(randomalienfire, number );         } 

when switch activities call mainhandler.removecallbacksandmessages(null); , thread.randomalienfire = null; yet still leaking entire activity. question is, there in basic skeleton causing memory leak? fact handler calling itself?

yes, implementation cause memory leak (i ran myself).

the problem have created circular reference. have declared runnable non-static inner class, means automatically maintain reference activity. runnable member variable of activity, closes circle. garbage collector never able free these objects since there living reference.

using static inner class weak reference activity safest way fix problem. you can see great code example here. if mainhandler non-static inner class, create second circular reference same reasons have same thing there.

setting mainhandler.removecallbacksandmessages(null); , thread.randomalienfire = null; work, have careful put code. perhaps code taking different path expect in cases , missing calls? this blog post describes else's similar experience approach.

in case, using runnable sequence animations on imageviews. rid of memory leaks, created static runnable class avoid circular reference. alone not enough me, found drawable still retaining reference fragment. calling myimageview.removecallbacksandmessages(arrowanimationrunnable); in ondestroy() in fragment solved leak. here solution:

public class myfragment extends sherlockfragment {      public static class saferunnable implements runnable {          private final weakreference<myfragment> parentreference;          public saferunnable(myfragment parent) {             parentreference = new weakreference<myfragment>(parent);         }          @override         public void run() {             if (parentreference != null) {                 final myfragment parent = parentreference.get();                 if (parent != null) {                     runwithparent(parent);                 }             }         }          public void runwithparent(myfragment parent) {          }     }       // anonymous instance of new runnable class not retain      reference fragment     private runnable arrowanimationrunnable = new saferunnable(this) {          @override         public void runwithparent(myfragment parent) {              // ... animation code              // repeat animation in 1 second             parent.myimageview.postdelayed(this, 1000);         }      };       private imageview myimageview;       @override     public view oncreateview(layoutinflater inflater, viewgroup container,          bundle savedinstancestate) {          view view = inflater.inflate(r.layout.my_layout, container, false);          // find image view , kick off animation after 1 second         myimageview = (imageview) view.findviewbyid(r.id.iv_arrow);         myimageview.postdelayed(arrowanimationrunnable, 1000);          return view;     }      @override     public void ondestroyview() {         super.ondestroyview();          // it's necessary remove callbacks here, otherwise message          // sitting in queue , outlive fragment. because          // reference in message still pointing fragment,          // fragment (and else) not garbage collected         myimageview.removecallbacks(arrowanimationrunnable);     } } 

Comments

Popular posts from this blog

basic authentication with http post params android -

vb.net - Virtual Keyboard commands -

How to get multiresult with multicondition in Sql Server -