Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I manually close HandlerThreads created by my application when destroying the activity?

My app is composed of a single Activity. In this activity, I'm creating multiple HandlerThreads which run in a loop to do socket blocking operations.

Currently I post a quit message to everyone of these HandlerThreads during my Activity.onDestroy().

Sometimes, when I open my app, close it and relaunch it, it crashes (many time due to posting a message to a handler thread which is not running).

My question is: What is the right way to close HandlerThread when I close my app? (Note that those threads might be blocking on a socket operation).

EDIT: More information: I have a pool of Handler Threads which is initiated in onCreate (No problem when I'm launching my app at the first time).

Each handler runnable loop is wrapped with an

 if (shouldRun) {
//body
} 
else { 
 close();
}

statement.

the close method remove all pending messages and runnables and post a message to the handler that will cause him to call its looper.quit(). This way, if the current handler thread is blocked by IO operation, only once it will finish it he will quit().

like image 893
Daniel L. Avatar asked Feb 18 '13 08:02

Daniel L.


People also ask

What is HandlerThread in Android?

android.os.HandlerThread. A Thread that has a Looper . The Looper can then be used to create Handler s. Note that just like with a regular Thread , Thread.

How do you use HandlerThread?

How do I use HandlerThreads. There are 2 main ways that I found to use HandlerThreads. Create a new HandlerThread, create a new Handler using this HandlerThread and post your tasks on this handler. Extend HandlerThread inside your CustomHandlerThread, create a Handler to process your task.


2 Answers

Yes, it would be a good idea to close it. Also make sure to remove your callbacks.

@Override
public void onDestroy() {
    super.onDestroy();
    handler.removeCallbacksAndMessages(null);
    handler.getLooper().quit();
}
like image 52
Andy McSherry Avatar answered Nov 15 '22 15:11

Andy McSherry


    /**
 * Ask the currently running looper to quit.  If the thread has not
 * been started or has finished (that is if {@link #getLooper} returns
 * null), then false is returned.  Otherwise the looper is asked to
 * quit and true is returned.
 */
public boolean quit() {
    Looper looper = getLooper();
    if (looper != null) {
        looper.quit();
        return true;
    }
    return false;
}

Above is the 'quit' method of the source code of HandlerThread.java, just invoke it directly.

Why should called quit? Below is 'run' method of the source code of HandlerThread.java.

    public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();//always loop except for a Message with null target

    mTid = -1;
}

The answer is 'loop is a 'while(true)' method,It will return until receive a Message with null target.

like image 33
Ql An Avatar answered Nov 15 '22 14:11

Ql An