[英]Activity.finish() doesn't kill the thread
我正在主要活动类中使用以下代码连接到Socket.io服务器。
private Socket socket; {
Options opts = new IO.Options();
opts.reconnection=true;
socket = IO.socket("Server ip",opts);
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
Log.w("Connection","Ok");
}
});
}
它会自动连接到另一个线程。然后,如果用户按下“后退”按钮,我将在以下行中运行:
this.finish();
所以,我先关闭活动,然后再使用onDestroy()
方法,如下所示:
@Override
protected void onDestroy() {
super.onDestroy();
Log.w("Destry","ok");
socket.disconnect();
socket=null;
}
但是,当我再次启动我的应用程序时, socket
变量的nullPointerException
崩溃了。
如果我使用System.exit(0)
而不是this.finish()
则当我再次启动该应用程序时,它运行良好,没有NullPointerException
我认为当我调用this.finish()
方法并且我不想使用System.exit(0)
时,线程并没有被杀死。
我该如何解决?
编辑:崩溃日志
02-12 22:52:22.304: E/AndroidRuntime(14804): FATAL EXCEPTION: EventThread
02-12 22:52:22.304: E/AndroidRuntime(14804): java.lang.NullPointerException
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.impact.ribony.MainActivity$2.call(MainActivity.java:275)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket.access$701(Socket.java:18)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket$5.run(Socket.java:166)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.thread.EventThread.exec(EventThread.java:50)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket.emit(Socket.java:162)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket.onconnect(Socket.java:353)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket.onpacket(Socket.java:276)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket.access$100(Socket.java:18)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket$2$2.call(Socket.java:101)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Manager.ondecoded(Manager.java:377)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Manager.access$1200(Manager.java:20)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Manager$3.call(Manager.java:351)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.parser.Parser$Decoder.add(Parser.java:156)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Manager.ondata(Manager.java:369)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Manager.access$1000(Manager.java:20)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Manager$2.call(Manager.java:342)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.Socket.onPacket(Socket.java:485)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.Socket.access$900(Socket.java:29)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.Socket$5.call(Socket.java:288)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.Transport.onPacket(Transport.java:121)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.transports.Polling.access$700(Polling.java:15)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.transports.Polling$2.call(Polling.java:122)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.parser.Parser.decodePayload(Parser.java:251)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.transports.Polling._onData(Polling.java:132)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.transports.Polling.onData(Polling.java:104)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.transports.PollingXHR$5$1.run(PollingXHR.java:113)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.thread.EventThread$2.run(EventThread.java:75)
02-12 22:52:22.304: E/AndroidRuntime(14804): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
02-12 22:52:22.304: E/AndroidRuntime(14804): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
02-12 22:52:22.304: E/AndroidRuntime(14804): at java.lang.Thread.run(Thread.java:841)
这是我正在运行的服务,用于处理我的SocketIO连接。 我为您清理了它,以便您可以重复使用它。
public class SocketIOConnection extends Service {
//you need constants to tell servise and activity what you are sending a message for
public static final int REGISTER_CHAT_ACTIVITY = 1;
public static final int MESSAGE_RECEIVED = 2;
final Messenger mMessenger = new Messenger(new IncomingHandler());
Messenger chat;
private Socket socket;
@Override
public void onCreate() {
try {
socket = IO.socket("IP HERE");
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
}
}).on("connected", new Emitter.Listener() {
@Override
public void call(Object... args) {
emitUserId();
}
})on("message", new Emitter.Listener() {
@Override
public void call(Object... args) {
//for example you are receiving a message with event name "message"
//you now send the information you need to update the UI
// to the activity which is actually showing the UI
//in this case i have a messenger (see above) named chat
//which is initiated below
//for now we just send a message
chat.send(Message.obtain(null, MESSAGE_RECEIVED, args[0])); //if you have more than one object (it is not a json) you can send the whole args array and handle it in the activity
}
});
//and add all the other on listeners here
socket.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (socket != null) {
socket.disconnect();
socket.connect();
} else {
try {
socket = IO.socket("IP HERE");
socket.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
//handle messages sent to service here
//second parameter in Message.obtain() is stored in msg.what
//so you need a switch case for the handling
switch(){
case REGISTER_CHAT_ACTIVITY:
chat = msg.replyTo;
break;
}
}
}
public class LocalBinder extends Binder {
SocketIOConnection getService() {
return SocketIOConnection.this;
}
}
}
在您的活动中,只需添加以下内容:
public class MyChatActivity extends Activity {
public static Messenger mService = null;
public final Messenger mMessenger = new Messenger(new IncomingHandler());
public boolean mIsBound;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout_id);
doBindService();
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
mService = new Messenger(service);
try {
Message msg = Message.obtain(null, SocketIOConnection.REGISTER_CHAT_ACTIVITY);
msg.replyTo = mMessenger;
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName className) {
mService = null;
}
};
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SocketIOConnection.MESSAGE_RECEIVED:
//here you have the objects sent to you via the socket
//you passed them as the third parameter of Message.obtain()
Object message = msg.obj;
//you can cast the object to the type you want and update the UI as you wish with the object
break;
default:
super.handleMessage(msg);
}
}
}
public void doBindService() {
if (!mIsBound) {
context.bindService(new Intent(context,
SocketIOConnection.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
}
}
如果你想了解如何活动和服务之间的通信是可能的,你可以阅读该文章。
编辑:在您的活动中覆盖此方法:
public void doUnbindService() {
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
}
}
@Override
protected void onPause() {
doUnbindService();
stopService(new Intent(yourActivity.class, SocketIOConnection.class));
super.onPause();
}
@Override
protected void onDestroy() {
doUnbindService();
stopService(new Intent(yourActivity.class, SocketIOConnection.class));
super.onDestroy();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.