Search code examples
androidconcurrencysynchronizationdispose

Stopping Handler runnable tasks when destroying activity


I usually delegate all Activities events to a separate controller class, which has a special method for handling events from Activity

@Override
public boolean handleMessage(int what, Object data) {
    switch (what) {
    case ExerciseViewEvent.STARTUP:
        workerHandler.post(new Runnable() {
            public void run() {
                onStartup();
            }
        });
        return true;
}

This is done in order to keep UI thread responsive and make all computations in background tasks.

However, when Activity.onDestroy() method is called by the system, controller.dispose() method is called, which cleans up all stuff in controller this way

@Override
protected synchronized void dispose() {
    .................
    if (model != null) {
        synchronized (model) {
            model.dispose();
        }
        model = null;
    }
    helper = null;
    .....................
    super.dispose();
}

As you can see, disposing of controller happens in UI thread, without delegating it to a handler thread.

The problem happens when, for example, onDestroy is called in the middle of onStartup() method: onDestroy cleans up the model and all other references, but inside onStartup method it tries to access the model at some point, but considering it is null, an exception is thrown.

What is the best way for resolving this issue? I do not want to lock every controller method because some of them may happen simultaneously without interfering each other.


Solution

  • In the dispose() method you should cleanup the workerHandler before disposing of the model. See the removeCallbacks or removeCallbacksAndMessage(null) methods in the Handler class. The latter method removes all callbacks and messages when the argument is null.