Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Threading: This Handler class should be static or leaks might occur [duplicate]

I am using a handler object to continue UI work after finished a time consuming task in a seperate thread. Had a problem of the above Lint warning and following was my approach.

[ Sample Handler object type 1 ] ->

Handler responseHandler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {
        super.handleMessage(msg);
        Toast.makeText(MainActivity.this, "Finished the long running task in seperate thread...", Toast.LENGTH_LONG).show();
    }       
};

[ Sample Handler object type 2 ] ->

Handler responseHandler = new Handler(new Handler.Callback() 
{       
    @Override
    public boolean handleMessage(Message msg) 
    {   
        Toast.makeText(MainActivity.this, "Finished long running task in a seperate thread...", Toast.LENGTH_LONG).show();
        return false;      // RETURN VALUE ????
    }
});

In the seperate thread(other than UI) when the time consuming task is done, it executes the following line to get the control back to UI thread(basically to the handler obj).

responseHandler.sendEmptyMessage(0);

The program works really fine with both types of handler objects, but with 1st type I am getting a Lint warning saying This Handler class should be static or leaks might occur.

Therefore I started using the 2nd type of handler object to avoid the Lint warning but the problem I've got is, I am not sure about the meaning of return value (true/false) in the 2nd way and also it works with either. I searched for this in google for so much but didn't get an exact answer explained this return value.

Yes, I saw this question had asked in many places in stackoverflow mainly reagrding the Lint warning, but my question is mainly about the return type in the 2nd way and to get it confirm if it's alright the way I solve the issue using the 2nd type of handler Obj.

Questions ->

1). Does anybody know what exacly this return value means(true/false) ?

2). Is it the correct thing I have done to get rid of the lint warning?

Thanks...

like image 477
JibW Avatar asked Aug 13 '13 10:08

JibW


2 Answers

Each handler is bound to the Looper of a thread, each Message is placed on a data structure, a message queue.

Message has a target variable that points to a Handler, a callback variable that points to a Runnable.

So, If you are using an anonymous class to create a Handler object (like in the first example), then know that anonymous/non-static inner classes hold a reference to outer objects (Activity ?). So, the message posted on queue, might be holding references to the Handler as target, and the Handler in turn holding a reference to the outer class, like Activity.

Now, a message can stay in the message queue for long intervals of time, as long as the thread is running. Meanwhile, the activity may have been dismissed. But it won't be garbage collected due to the obscure indirect reference of it, which the message has. Note that the Looper and Message Queue stay around as long as the thread is running.

In the second example, you are not creating an anonymous Handler class. You are using the handler constructor and passing it an anonymous Callback object. This might stop Lint from complaining, But I doubt this is a good approach. Just avoid inner classes, avoid passing Activity or context references to Handler.

Update:

The Handler's dispatchMessage() gets messages due to be processed, where it checks if a callback has been provided, then if callback is provided, it doesn't calls handleMessage(), if callback's handleMessage() returns true:

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg); //--won't be called if you return true.
    }
}
like image 83
S.D. Avatar answered Oct 03 '22 00:10

S.D.


I found some important info about memory leak by inner class like handler and want to share with you :

How to Leak a Context: Handlers & Inner Classes And I think the overridden method of Handler class will not return anything as you can check : handleMessage()

You have overridden Java Handler class not Android Handler, you can see handleMessage() of Java Handler class is having return statement and you can check reason also for return statement over here : boolean handleMessage(C context)

like image 44
Harish Godara Avatar answered Oct 03 '22 02:10

Harish Godara