2012-04-19 8 views
0

リモートサービスに接続するモジュールを作成します。Android:リモートメッセンジャーサービスの呼び出し時にメソッドを同期

このモジュールは、開発者が特定の(ブルートゥース)ハードウェアに接続するためにアプリケーションで使用できます。その後、市場で別々に更新できる単一のリモートサービスに接続する必要があります。

リモートサービスでは、同時に使用しているすべてのアプリケーション(Bluetooth経由の1つの接続のみ)に対して1つのスレッドしか使用できないため、AIDLよりもメッセンジャーアプローチを選択しました。

私のパブリックAPIで同期メソッドを提供したいが、サービスがハンドラで返されるようになりました。私が理解している限り、ハンドラは常に現在のタスクが終了するまで待ちます。では、差分スレッドで答えを得る方法はありますか?

私はそれがしたいとの同期方法のコード:事前に

responseDataSync = new Sync<ResponseData>(); 

    // Send message 
    Message msg = Message.obtain(null, Constants.DATA, 1, 0); 

    send(msg); 

    try { 
     ResponseData responseData = responseDataSync.get(); 

     // with responseDataSync using a countdown latch to synchronize... 
// but it never fires thanks to the handler. 
//etc... 

感謝。私の質問がやや理解できたと思います);

/EDIT: サーバーからデータを返すメソッドが必要です。以下のような

public ResponseData returnResponse(Data dataToSend) 

が、その後、私は何を返すからブロックハンドラをスレッドで立ち往生していますので、私は、サービスの帰りを待つことができない...

+0

のように働くかもしれないメッセージを待ちますあなたのapk経由で、そしてそのサービスを利用したい他のアプリに含まれなければならないパブリックAPIを使用していますか? – zapl

+0

あなたは私を持っています。 ;)ライブラリには追加機能があり、できるだけシンプルにサービスにアクセスする必要があるため、同期メソッドの必要性があります – domenukk

答えて

3

Handlerは、単一のメッセージキューに関連付けられています。任意のスレッドからMessageを送信すると、そこにエンキューされます。

すべてのメッセージを受信するスレッドは、適切なメッセージをキューから取り出し、それを1つずつ処理します。

ハンドラがあり、ハンドラを通してすべてのメッセージを実行すると、すべてが1つのスレッドで処理されるため、同期は必要ありません。

編集:バックグラウンドスレッドでメッセージを処理するハンドラを作成するには:

HandlerThread ht = new HandlerThread("threadName"); 
ht.start(); 
Looper looper = ht.getLooper(); 
Handler.Callback callback = new Handler.Callback() { 

    @Override 
    public boolean handleMessage(Message msg) { 
     // handled messages are handled in background thread 
     return true; 
    } 
}; 
Handler handler = new Handler(looper, callback); 

handler.sendEmptyMessage(1337); 

EDIT2:あなたは配布(リモート)サービスを持っているこの

// available for all threads somehow 
final Object waitOnMe = new Object(); 

HandlerThread ht = new HandlerThread("threadName"); 
ht.start(); 
Looper looper = ht.getLooper(); 
Handler.Callback callback = new Handler.Callback() { 

    @Override 
    public boolean handleMessage(Message msg) { 
     // handled messages are handled in background thread 
     // then notify about finished message. 
     synchronized (waitOnMe) { 
      waitOnMe.notifyAll(); 
     } 
     return true; 
    } 
}; 
Handler handler = new Handler(looper, callback); 

// in a different Thread: 
synchronized (waitOnMe) { 
    handler.sendEmptyMessage(1337); 
    try { 
     waitOnMe.wait(); 
    } catch (InterruptedException e) { 
     // we should have gotten our answer now. 
    } 
} 
+0

ありがとうございます。しかしそれは私の問題です。私は同期メソッドを持っていたいと思っていました。例えば、 public SomeValue returnSomeValue(SomeParameter someParameter) しかし、私のメソッドが実行されている限り、ハンドラは何も返しませんので、サービスからの結果を待つことはできません... – domenukk

+0

わかりました。それはもう少し複雑です。基本的には、最初にメッセージをあなたのサービスに送り、 'returnSomeValue()'内のサービスから受け取ったメッセージを待つメカニズムを置く必要があります。もう1つの可能性は、これを内部的に処理するAIDLインタフェースを持つ通常のサービスです。あなたはそのようなサービスで本当のメソッドを呼び出すことができますが、あなたがそれをやりたくない場合は 'returnSomeValue()'でサービス接続を管理する必要があります。 – zapl

+0

私は最初のアプローチが必要です。 AIDLの問題は、基本的にすべてを書き直す必要があり、自分でMessengersを使って自然に同期を実装する必要があるということです。 ハンドラを待つ方法はありますか?ハンドラが同期されているので、関数がそれを待つ方法を見つけることができないようです。 (関数が待機している間は、ハンドラは戻りません)何らかの形で別のスレッドにハンドラを置くことはできますか?私はHandlerThreadに遭遇しましたが、それが私に役立つのかどうかはわかりませんでした... – domenukk

関連する問題