Alex Rivera | Logout

Handlers and memory leaks in Android

Asked 2012-07-01T01:09:11.350
48

Please have a look at the code below:

public class MyGridFragment extends Fragment{
    
    Handler myhandler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            switch (message.what) {
                case 2:   
                    ArrayList<HashMap<String,String>> theurls = (ArrayList<HashMap<String,String>>) message.obj;
                    urls.addAll(theurls);
                    theimageAdapter.notifyDataSetChanged();
                    dismissBusyDialog();
                    break;
            }
        }
    }
}

When I use handler like this I get a warning "handler should be static, else it is prone to memory leaks." Can someone tell me what is the best way to do this?

Edit
Report

2 Answers

4

If you read docs about AccountManager or PendingIntent, you will see that some methods take Handler as one of arguments.

For example:

  • onFinished - The object to call back on when the send has completed, or null for no callback.
  • handler - Handler identifying the thread on which the callback should happen. If null, the callback will happen from the thread pool of the process.

Imagine the situation. Some Activity calls PendingIntent.send(...) and put the non-static inner subclass of Handler. And then activity is destroyed. But inner class lives.

Inner class still holds a link to destroyed activity, it cannot be garbage-collected.

If you're not planning to send your handler to such methods, you have nothing to worry about.

answered 2012-07-03T12:10:43.420
0

I run into the same issue and I find that it is one of this topics with many questions and few answeres. My solution is simple and I hope it can help someone:

/* BEFORE */
private Handler mHandler= new Handler() {
        @Override public void handleMessage(Message msg) {
        this.doSomething();
    };
};

We can create a static Handler subclass that simply runs a Runnable. The actual handler instance will know what to do through the runnable that will have access to instance variables.

/* AFTER */
static class RunnableHandler extends Handler {
    private Runnable mRunnable;
    public RunnableHandler(Runnable runnable) { 
        mRunnable = runnable;
    }
    @Override public void handleMessage(Message msg) {
        mRunnable.run();
    };
}
private RunnableHandler mHandler = new RunnableHandler(new Runnable() {
    @Override public void run() {
        this.doSomething();
    } });

The warning is gone while the funcionality is the same.

answered 2012-07-05T10:27:26.233

Your Answer