如何保持连接线程活着? (我需要使用守护进程吗?)

时间:2012-07-11 18:56:29

标签: java android multithreading

我的Android应用程序使用线程从通过USB连接的PC侦听套接字连接。在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();
    }
}.

多年来,我一直在摸不着头脑,想知道为什么我从未在触摸事件后看到INNER_TAG的值出现在我的日志中。我可以使用日志调试来跟踪执行到coordHandler!=null块,但处理程序似乎永远不会触发。

然后它让我感到震惊:线程可能在完成连接后退出。 D'呃!不太确定我以前发生过什么事情,但我会因为Loop正在做一些神奇的事情而将其归咎于此。

所以我的问题是:如何保持我的线程运行?官方Android dev reference on threads简要提及

  

线程也可以成为守护进程,使其在后台运行。

这自然使我的* nix感觉刺痛。 (顺便说一下,你看过新的蜘蛛侠电影了吗?它还不错。)守护进程是答案吗?或者我完全失去了情节?

2 个答案:

答案 0 :(得分:2)

在Android中使用服务

您可以使用服务在后台运行..

请看这个链接:

http://developer.android.com/reference/android/app/Service.html

请参阅此链接以获取示例:

Example: Communication between Activity and Service using Messaging

答案 1 :(得分:0)

  1. connection = new Thread(new ServerThread());更改为:connection = new ServerThread();

  2. 设置/获取处理程序实例时可能会添加synchronized块(毕竟它位于不同的线程中))

  3. 循环实际上是神奇的;)

  4. 在onDestroy中退出Looper for serverThread

  5. 最后但并非最不重要(虽然它与Handler / Looper主题无关,可能是你从未在日志中看到你期望的原因):而不是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.,因此可能永远不会调用此处理程序方法

  6. 编辑: 你确定它执行sendMessage吗?那么为什么你要使用Log.v?它假定您将日志记录级别设置为详细,否则将放弃日志。我建议使用Log.i

    也许试试这段代码:

    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();
        }
    }