0

したがって、私の意図は次のとおりです。主にメインUIから送信要求(UDP)を受け取り、その応答を待機してメインUIにディスパッチされるバックグラウンドサービスが必要です。これはかなり同期したプロセスです。しかし、それに加えて、ネットワークを介していつでも受信できる非同期メッセージをサービスが待機するようにします。たとえば、ネットワーククライアントが私に通知したり、エラーを報告したりします。これを実装するための最良の方法は何でしょうか?IPCの場合、Messengerクラスはデータの処理に役立つ可能性があります。ここにある「リモートメッセンジャーサービスサンプル」のように実装できますかhttp://developer.android.com/reference/android/app/Service.html ??

どんな助けでも大歓迎です。

4

1 に答える 1

1

私のプロジェクトでは、永続的に実行されているサービスがあります。

このサービスで作成されたスレッドも3つあるので、すべてバックグラウンドで実行されます。それらのそれぞれがいくつかの作業を行い、httpデータも要求します。私はハンドラーを使用してそれを行い、メッセージキューを管理しました。

それは簡単でうまく成長し、プロジェクトの次元と複雑さを増します。

だから、はい、私はそのように従う必要があります。

PS:バックグラウンドで作業する必要がある場合は、PowerManagerでwake_locksを取得して、電話がスタンバイ状態になったときにCPUがオンのままになるようにしてください(電話がスタンバイ状態になったときにスレッドが機能しなくなる理由を理解するのに数日かかりました)。

メインスレッドで、4つのハンドラー(recordingThreadとの両面通信用に2つ、sendingThreadとの両面通信用に2つ)を宣言しました。次に、他の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();

また、ハンドラーは作成されたスレッドに自動的に関連付けられることに注意してください。ハンドラーAがスレッドT1で作成された場合、Aの参照をT2とT3に渡すことができます。これらのスレッドはT1にメッセージを送信できますが、その逆はできません。これは、2面通信を有効にするために4つのハンドラーを作成したためです。

于 2012-06-03T17:54:03.220 に答える