0

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

任何帮助表示赞赏。

4

1 回答 1

1

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

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

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

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

PS:如果你必须在后台工作,记得用PowerManager获取wake_locks,确保你在手机待机时CPU会保持开启(我花了几天时间才明​​白为什么手机待机时线程停止工作)。

在主线程中,我声明了4个处理程序(2个用于与recordingThread的两侧通信,2个用于与sendThread的两侧通信):然后简单地创建其他2个线程;看看 Looper 调用:当代码执行时不要让你的线程死掉,并等待传入​​的消息来自在它自己的执行内部创建的处理程序(在这种情况下是在 run() 方法中)。我还为与线程关联的每个处理程序声明了一个私有类:这样每个线程都有自己的通道来与不同的“动作”进行通信(切换案例)。还有另一个处理程序,recordingThread 处理程序,这里没有显示;但想法是一样的:

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 个处理程序,用于启用 2 方通信。

于 2012-06-03T17:54:03.220 回答