タイトルが示すように、Android のスレッド間で汎用の非同期要求/応答メカニズムを実装するエレガントな方法を探しています。
次のことができる必要があります。
- さまざまなタイプの引数を使用して別のオブジェクトにリクエストを非同期に送信する
- 送信者のキューに応答を投稿することにより、そのオブジェクトにオプションで非同期に応答させる
Thread を拡張するタイプ Manager のオブジェクトがあるとします。そのような各 Manager には Handler と Looper があり、それぞれが互いのキューにメッセージを非同期的にプッシュできるようになっています。
単純化して疑似コードで、これを次のように実装します。
Manager extends Thread
{
// loop forever, pulling a request from the queue and handling it
listenToRequests()
{
Looper.prepare()
m_handler = new Handler()
{
handleMessage(msg)
{
switch(msg.what)
{
case REQUEST_TYPE_0:
handleRequestType0(msg.object, msg.args);
break;
case REQUEST_TYPE_1:
handleRequestType1(msg.object, msg.args);
break;
...
}
}
}
}
他のマネージャー インスタンスは、メッセージを割り当て、入力し、ターゲット マネージャーに送信する必要があります。
msg = targetManager.getHandler().obtainMessage();
msg.what = REQUEST_TYPE_0;
msg.object = this;
msg.args = ...;
msg.sendToTarget();
ターゲット マネージャは、送信側で Message() を取得し、応答メッセージを入力して送信できます。
上記のコードの問題は、両方の要件を満たしている一方で、メッセージごとに実装する煩わしいボイラープレート コードが多数あることです。
- いくつかの列挙でメッセージ タイプを定義します (例: REQUEST_TYPE_N)
- 引数をマーシャリングするためのメッセージへの引数の母集団
- メッセージをディスパッチして処理する switch ケースを追加する
Runnable を使用すると、引数のパッキングの問題が解決され、(スイッチ/ケースを介して) メッセージのディスパッチが排除されます。
public void doRequest0(args)
{
handler.post(new Runnable()
{
@Override
public void run()
{
// do stuff with args...
args.sender.request0Response(...);
}
});
}
これの問題は、コールバックの代わりに、応答用のインターフェイスを宣言して実装する必要があることです。そのようなインターフェイス関数ごとに、handler.post(new Runnable() ... で装飾する必要があります。これも多くの定型コードのようです。
私が見逃している他のオプションはありますか?私の要件は控えめに見えますが、私のソリューションは構文的に非常に複雑です。