Zack
Zack

Reputation: 871

Handler Memory Leak?

I have a Handler which is declared on the main thread:

  mainHandler = new Handler() {

            @Override
            public void handleMessage(Message msg) {

                switch (msg.what) {

                    case 1:

                        Bundle bundle = msg.getData();
                        mTextView.setText(bundle.getString("message"));
                        break;

                    . . .

                    default:
                        super.handleMessage(msg);
                        break;
                }
            }
        };

Where mTextView is a TextView defined onCreate().

I have a task which is used in a separate thread. The runnable stores mainHandler from the main thread and tells it to send messages:

public class SomeRunnable implements Runnable {

    private Handler mHandler;

    public SomeRunnable(Handler handler) throws IOException {
        . . .    
        mHandler = handler;
    }

    @Override
    public void run() {

        while (!Thread.currentThread().isInterrupted()) {
            try {
                    . . .

                    Message msg = mHandler.obtainMessage();
                    . . .
                    mHandler.sendMessage(msg);
                }

            } catch (IOException e) {
                Log.e("Error", e.hashCode() + ": " + e.getLocalizedMessage());
            }
        }
    }

I have seen that you can potentially create memory leaks by using methods such as Handler#postDelayed() if the Handler class is not static. But, I am using Handler#sendMessage() which instantly puts a Message in the message queue.

Am I still in danger of having a memory leak? Even with:

  @Override
    protected void onDestroy() {
        super.onDestroy();

        mThread.interrupt();
        mainHandler.removeCallbacksAndMessages(null);
    }

Thank you!

Upvotes: 1

Views: 940

Answers (1)

323go
323go

Reputation: 14274

To address all eventualities, you could make mHandler a WeakReference as below:

public class SomeRunnable implements Runnable {

    private WeakReference<Handler> mHandlerRef;

    public SomeRunnable(Handler handler) throws IOException {
        . . .    
        mHandlerRef = new WeakReference<Handler>( handler );
    }

    @Override
    public void run() {

        while (!Thread.currentThread().isInterrupted()) {
            try {
                    . . .
                    Handler mHandler = mHandlerRef.get();
                    if( mHandler != null ) {
                        Message msg = mHandler.obtainMessage();
                        . . .
                        mHandler.sendMessage(msg);
                    }
                }

            } catch (IOException e) {
                Log.e("Error", e.hashCode() + ": " + e.getLocalizedMessage());
            }
        }
    }
}

Upvotes: 1

Related Questions