[英]How can I keep a connection thread alive? (Do I need to use a daemon?)
My Android application uses a thread to listen for a sockets connection from a PC connected via USB. 我的Android应用程序使用线程侦听来自通过USB连接的PC的套接字连接。 At some point after the PC opens the connection (in response to some user driven event) I want to send some data over it.
在PC打开连接后的某个时刻(响应某些用户驱动的事件),我想通过它发送一些数据。
public void onCreate(Bundle savedInstanceState) {
// SNIP: stuff and nonsense
connection = new Thread(new ServerThread());
connection.start();
}
public boolean onTouchEvent(MotionEvent event) {
// SNIP: decide what to do; create string 'coordString'
Message coordMsg = coordHandler.obtainMessage();
Bundle coordMsgData = new Bundle();
coordMsgData.putString("coords", coordString);
coordMsg.setData(coordMsgData);
if(coordHandler!=null)
{
coordHandler.sendMessage(coordMsg);
}
return false;
}
public class ServerThread extends Thread
{
public void run() {
this.setName("serverThread");
Looper.prepare();
coordHandler = new Handler()
{
@Override
public void handleMessage(Message msg) {
Log.v(INNER_TAG,"here");
}
};
// SNIP: Connection logic here
Looper.loop();
}
}.
For ages I was scratching my head wondering why I never saw the value of INNER_TAG
appear in my logs after touch events. 很久
INNER_TAG
我一直在想知道为什么我在触摸事件之后为什么从未在日志中看到INNER_TAG
的值。 I could use log-debugging to trace the execution into the coordHandler!=null
block, but the handler never seemed to fire. 我可以使用日志调试将执行跟踪到
coordHandler!=null
块中,但是该处理程序似乎从未触发过。
Then it struck me: the thread is probably exiting after completing the connection. 然后让我震惊:完成连接后,线程可能正在退出。 D'uh!
'! Not quite sure what I thought was happening before, but I'll blame it on a belief that
Loop
was doing something magical. 不太确定我之前的想法,但我会认为这是
Loop
所做的不可思议的事情。
So my question is: How can I keep my thread running? 所以我的问题是:如何保持线程运行? The official Android dev reference on threads briefly mentions that
官方Android开发人员在线程上的参考简要提及
A Thread can also be made a daemon, which makes it run in the background.
也可以将Thread设为守护程序,使其在后台运行。
This naturally made my *nix senses tingle. 这自然使我的* nix感到发麻。 (Incidentally, have you seen the new Spiderman film yet? It's pretty good.) Is daemonisation the answer?
(顺便说一句,您看过新的《蜘蛛侠》电影吗?还不错。)守护进程是答案吗? Or have I completely lost the plot?
还是我完全失去了情节?
Use Service in Android. 在Android中使用服务 。
You can use Service to run at the background.. 您可以使用Service在后台运行。
See this link: 看到这个链接:
http://developer.android.com/reference/android/app/Service.html http://developer.android.com/reference/android/app/Service.html
See this link for the example: 有关示例,请参见此链接:
Example: Communication between Activity and Service using Messaging 示例:使用消息传递在活动和服务之间进行通信
Change connection = new Thread(new ServerThread());
更改
connection = new Thread(new ServerThread());
to: connection = new ServerThread();
到:
connection = new ServerThread();
Maybe add synchronized blocks when setting/getting handler instance (it is in different threads after all :)) 可能在设置/获取处理程序实例时添加了同步块(毕竟它位于不同的线程中:)
Loop actually does the magic ;) 循环实际上是神奇的;)
In onDestroy quit Looper for serverThread 在onDestroy退出serverThread的Looper
And last but not least (although it does not concern Handler/Looper subject is probably the reason why you never see in logs what you expect): instead of boolean onTouchEvent(MotionEvent event)
use boolean dispatchTouchEvent(MotionEvent ev)
as onTouchEvent due to docs is Called when a touch screen event was not handled by any of the views under it.
最后但并非最不重要的一点(尽管它不涉及Handler / Looper主题,这可能是您从未在日志中看到期望的原因的原因):由于文档的缘故,请使用
boolean dispatchTouchEvent(MotionEvent ev)
MotionEvent boolean dispatchTouchEvent(MotionEvent ev)
代替boolean onTouchEvent(MotionEvent event)
boolean dispatchTouchEvent(MotionEvent ev)
作为onTouchEvent Called when a touch screen event was not handled by any of the views under it.
so probably this handler method is never called 所以可能永远不会调用此处理程序方法
EDIT: Are you sure it executes sendMessage? 编辑:您确定它执行sendMessage吗? And by the way why do you use
Log.v
? 以及为什么您要使用
Log.v
? it assumes you have logging level set to verbose otherwise the logs will be abandoned. 假设您已将日志记录级别设置为详细,否则日志将被放弃。 I suggest to use rather
Log.i
. 我建议使用宁可使用
Log.i
Maybe try this code: 也许尝试下面的代码:
ServerThread connection;
Handler coordHandler;
public void onCreate(Bundle savedInstanceState) {
connection = new ServerThread();
connection.start();
}
@Override
protected void onDestroy() {
synchronized (this) {
if(coordHandler != null) {
coordHandler.getLooper().quit();
}
}
super.onDestroy();
}
public boolean dispatchTouchEvent(MotionEvent event) {
synchronized (this) {
if(coordHandler == null) {
Log.i(INNER_TAG, "Handler is null");
}
else {
Log.i(INNER_TAG, "Handler exists");
coordHandler.sendMessage(
coordHandler.obtainMessage(
0, event.toString()));
}
}
return false;
}
synchronized void setCoordHandler(Handler handler) {
coordHandler = handler;
}
public class ServerThread extends Thread {
public void run() {
this.setName("serverThread");
Looper.prepare();
setCoordHandler(new Handler() {
@Override
public void handleMessage(Message msg) {
Log.i(INNER_TAG, "Inside handler");
}
});
Looper.loop();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.