Rumah > Soal Jawab > teks badan
由于ServerSocket.accept是一个阻塞函数,所以服务器Socket得放在一个新的线程中以免阻塞UI线程。这个新的线程我是用Handler和HandlerThread新建的。而这个新的线程是放在服务里面创建的。最初我是把关闭ServerSoket函数放在finally里面,在测试的时候,我先是开启了服务器Socket,没有连接的时候我就unbindService,然后在service的onDestroy回调中用handler.getLooper().quit()来关闭线程,可是我发现这样无法关闭线程,因为accept是阻塞的,所以quit()这个消息不会被处理,线程自然不会被关闭,finally里面的close也不会执行。于是第二次我把ServerSocket作为service里面的一个全局变量,在onDestroy里关闭线程之前,先close掉serverSocket,这样accept函数会退出,线程自然也能关闭了,但不好的事情发生了,之前的造作完成后,UI县城被阻塞了,ddms里显示main线程的状态变成了Runnable,这我就不懂了,我只是在主线程关闭了serverSocket,并且关闭了用于serverSocket监听连接的线程,但是怎么会阻塞掉UI线程呢?忘大神解惑!
主要代码如下:
@Override
public void onCreate() {
super.onCreate();
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this,getMainLooper(),null);
wifiReceiver = new WiFiDirectBroadcastReceiver(this);
registerReceiver(wifiReceiver,getIntentFilter());
setEndAccept(false);
HandlerThread server = new HandlerThread("wifi_server");
server.start();
serverAccept = new Handler(server.getLooper(),this);
//open server socket
serverAccept.obtainMessage(OPEN_SERVER,-1,-1,null).sendToTarget();
//startServerSocket = new OpenServerSocket();
//serverAccept.post(startServerSocket);
}
@Override
public boolean handleMessage(Message message) {
switch (message.what) {
case OPEN_SERVER:
openServerSocket();
break;
case OPEN_READING:
startReading();
break;
}
message.recycle();
return true;
}
/**
* create and open a server socket
*/
private void openServerSocket() {
try {
if(serverSocket == null) {
serverSocket = new ServerSocket(port);
}
while (!getEndAccept()) {
Log.e(TAG,"waiting accept ...");
clientSocket = serverSocket.accept();
openWorkThread();
}
} catch (Exception e) {
Log.e(TAG,"error in openServerSocket" + e.getMessage(),e);
}
}
private void closeServerSocket() {
if(serverSocket != null && !serverSocket.isClosed()) {
try {
serverSocket.close();
}catch (Exception e) {
e.printStackTrace();
}finally {
serverSocket = null;
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (!getEndAccept()) {
setEndAccept(true);
Log.e(TAG,"start to close server thread");
//close Looper Thread
closeServerSocket();
//serverAccept.removeCallbacks(startServerSocket);
serverAccept.getLooper().quit();
Log.e(TAG,"end to close server thread");
}
wifiReceiver = null;
channel = null;
manager = null;
}