在自己的网络任务中拥有长期运行的服务

时间:2012-06-03 13:06:33

标签: android multithreading

所以我的意图如下: 我需要一个后台服务,主要从主UI获取发送请求(UDP)并等待其响应,然后将其分派回主UI。这是一个非常同步的过程。但另外,我希望服务等待可以通过网络随时接收的异步消息,例如网络客户端想要通知我或报告错误。 实现这个的最佳方法是什么? 对于IPC来说,Messenger类可以用于处理数据。 是否可以像http://developer.android.com/reference/android/app/Service.html ??

中的“远程信使服务示例”一样实施

感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

在我的项目中,我有一项永久运行的服务。

我还在此服务中创建了3个线程,因此全部都在后台运行。他们每个人都做了一些工作,也请求http数据:我已经使用Handler完成了它,管理了消息队列。

它很容易并且增长良好,增加了项目的维度和复杂性。

所以,是的,我应该这样做。

PS:如果你必须在后台工作,记得用PowerManager获取wake_locks,确保你在手机进入待机状态时CPU保持开启状态(我花了几天时间来理解为什么线程在手机进入时停止运行待机)。

在主线程中,我声明了4个处理程序(2个用于与recordingThread的双方通信,2个用于与sendingThread的双方通信): 然后简单地创建另外2个线程;看看Looper调用:在代码执行时不需要让你的线程死掉,并且等待在自己的执行中创建的处理程序上传入的消息(在这种情况下在run()方法中)。 我还为与线程关联的每个处理程序声明了一个私有类:这样每个线程都有自己的通道来与不同的'action'进行通信(switch case)。 还有另一个处理程序,recordThread处理程序,这里没有显示;但想法是一样的:

private Handler m_recordingThreadHandler, m_sendingThreadHandler,
            m_thisRecordingThreadhandler, m_thisSendingThreadHandler;


public void run() {
        Looper.prepare();

        m_thisRecordingThreadhandler = new UpdRecHandler();
        m_recordingThread = new RecordingThread(m_mainThreadContext,
                m_thisRecordingThreadhandler, m_configuration, m_picturesDir);
        m_recordingThread.setName("recordingThread");
        m_recordingThread.start();

        m_thisSendingThreadHandler = new UpdSenHandler();
        m_sendingThread = new SendingThread(m_mainThreadContext,
                m_thisSendingThreadHandler, m_configuration);
        m_sendingThread.setName("sendingThread");
        m_sendingThread.start();

        Looper.loop();

    }

private class UpdRecHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            Message m;

            switch (msg.what) {

            case Utils.SEND_THIS_THREAD_HANDLER:
                Log.i(TAG, "Ricevuto Handler di recordingThread.");

                m_recordingThreadHandler = (Handler) msg.obj;
                m_recordingThreadReady = true;
                checkForAllThreadsReady();

                break;

            case Utils.FORCE_RESET:
                Log.i(TAG,
                        "RecordingThread ha compeltato la procedura per il reset.");
                m_recordingThreadResetted = true;
                checkForThreadsResetted();
                break;
...more cases...
}

此代码来自recordingThread类。 一旦创建,就会执行run方法,在这个方法中,我传递给主线程(前面看到的代码)这个线程的处理程序,在这个run()方法中创建:这样我启用了双边通信。 再次,在recordingThread中我为处理程序创建一个私有类。一旦执行了run方法,我再次调用Looper调用让线程处于活动状态。

public void run() {
        Looper.prepare();

        Log.i(TAG, "In esecuzione, mando il mio handler a updateThread");

        m_thisThreadHandler = new RecUpdHandler();
        m_mainThreadHandler.obtainMessage(Utils.SEND_THIS_THREAD_HANDLER,
                m_thisThreadHandler).sendToTarget();

        Looper.loop();
    }



private class RecUpdHandler extends Handler {

        public void handleMessage(Message msg) {
            Message m;

            switch (msg.what) {

            case Utils.TAKE_PHOTO:
                ...do work....
                break;
               case Utils.UPDATE_CONFIGURATION:
                ... do other work...
                break;

}

如果你想让你的线程终止,你只需要杀死与该线程关联的Looper,如下所示:

Looper.myLooper().quit();

请记住,处理程序自动关联到创建它的线程:如果在线程T1中创建处理程序A,则可以将A的引用传递给T2和T3。那些线程然后能够向T1发送消息,但不是反之亦然。 那是因为我创建了4个处理程序,用于启用双方通信。