I have a Service
that spawns a Thread
to connect to a third-party and it runs fine. However, if I go to settings and stop the service, it continues to run. It disappears from the Running Services in settings and the onDestroy
method is called, but I still see each method in the Service
being called. I'm assuming that I'm not using the Thread
correctly, but I don't see why the service would continue running... unless it keeps running until all of the threads are done.
public class DataProcessorService extends Service {
private ServiceState _state;
private ConnectThread _connectThread;
private Handler _handler = new Handler() {
public synchronized void handleMessage(Message msg) {
stopConnectThread();
onNextState(); // Goes to state开发者_C百科 after Connecting
}
};
@Override
public void onCreate() {
logger.debug("onCreate called");
_state = ServiceState.readState(this);
switch (_state) {
...
case CONNECTING:
onConnecting();
break;
...
}
}
@Override
public void onDestroy() {
logger.debug("onDestroy called");
stopConnectThread();
ServiceState.saveState(this, _state);
}
private void onConnecting() {
_state = ServiceState.CONNECTING;
logger.debug("onConnecting called");
_connectThread = new ConnectThread(this, _handler);
_connectThread.setDaemon(true);
_connectThread.start();
}
private void stopConnectThread() {
if (_connectThread != null) {
_connectThread.interrupt();
_connectThread = null;
}
}
}
Here's my ConnectThread
class (I also tried doing what was suggested here which is the commented sections):
public class ConnectThread extends Thread {
private final Context _context;
private final Handler _handler;
// private volatile Thread runner;
public ConnectThread(Context context, Handler handler) {
super("ConnectThread");
this._context = context;
this._handler = handler;
}
// public synchronized void startThread() {
// if (runner == null) {
// runner = new Thread(this);
// runner.start();
// }
// }
//
// public synchronized void stopThread() {
// if (runner != null) {
// Thread moribund = runner;
// runner = null;
// moribund.interrupt();
// }
// }
@Override
public void run() {
Looper.prepare();
// if (Thread.currentThread() == runner) {
logger.debug("Service started");
Thread.sleep(5000); //inside try-catch
// }
Looper.loop();
}
}
When I look in DDMS, it shows multiple ConnectThread
s and they're each in the wait
status, so I'm assuming they're finishing and not being killed and that may be preventing my Service from stopping. Does anyone see why the issue is happening, or know how to fix it?
EDIT: I'm now starting to think it may be because I need a Looper.quit()
call somewhere. I'll need to read up on Looper
and Handler
more. I started to look at HandlerThread
but I'm not real clear on what Loopers are for, yet. Is passing a Handler
to my ConnectThread
a bad idea?
You have to stop the Looper from looping in stopConnectThread(). Just interrupting the Thread doesn't won't stop the Looper. Try this:
in ConnectThread class add:
private Looper myLooper; // A reference to the Looper for this Thread
public void stopLooper() {
// Tell Looper to stop looping
myLooper.quit();
}
in ConnectThread.run() method, after Looper.prepare()
add:
myLooper = Looper.myLooper(); // Get the Looper associated with this Thread
in stopConnectThread(), instead of _connectThread.interrupt();
do this:
_connectThread.stopLooper();
精彩评论