这是客户端消息传递部分的代码
SparseArray<CountDownLatch> lockArray = new SparseArray<>();
SparseArray<Bundle> msgDataArray = new SparseArray<>();
public Bundle sendAndWaitResponse(Message msg) throws
RemoteException, InterruptedException {
int msgId = msg.arg2;
Log.d("PlatformConnector", "Sending message to service, Type: "
+ msg.what + ", msgId: " + msg.arg2);
CountDownLatch latch = new CountDownLatch(1);
lockArray.put(msgId, latch);
platformMessenger.send(msg);
latch.await();
Bundle response = msgDataArray.get(msgId);
lockArray.delete(msgId);
msgDataArray.delete(msgId);
return response;
}
void storeResponseAndNotify(Message msg) {
int msgId = msg.arg2;
// Because the message itself is recycled after Handler returns,
// we should store only the data of message
msgDataArray.put(msgId, msg.getData());
lockArray.get(msgId).countDown();
}
private class ClientMessageHandler extends Handler {
@Override
public void handleMessage(Message msg) {
storeResponseAndNotify(msg);
}
}
这是使用上述代码的示例。
RandomInt.getNextInt() 是我自定义的静态方法,用Random.nextInt() 生成随机整数。
public JSONObject doSomething(JSONObject object) {
Message msg = Message.obtain(null, Constants.MESSAGE_SOMETHING, 0, RandomInt.getNextInt());
Bundle bundle = new Bundle();
bundle.putString(Constants.MESSAGE_DATA_SOMETHING, object.toString());
msg.setData(bundle);
try {
Bundle responseData = sendAndWaitResponse(msg);
return new JSONObject(responseData.getString(Constants.MESSAGE_DATA_RETURN));
} catch (RemoteException e) {
Log.e(TAG, "Failed to send message to platform");
e.printStackTrace();
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted while waiting message from platform");
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
顺序如下,
- 客户端准备
Message并将其arg2设置为某个随机整数
(这个整数将是同步的消息 ID)。
- 客户准备新的
CountDownLatch并把它放到LockArray。
- 客户端用
sendAndWaitResponse()发送消息。它通过Messenger 向服务发送消息并调用latch.await()。
- 服务进程接收消息并准备回复消息。此回复消息的
arg2 应与收到的消息相同。
- 服务通过
Messenger在replyTo中向客户端发送回复消息。
- 客户端消息处理程序使用
storeResponseAndNotify 处理消息。
- 当Client线程的阻塞结束时,响应数据已经准备好在
msgDataArray中了。
CountDownLatch 是阻塞和解除阻塞线程的简单开关。
(http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)
SparseArray 类似于HashMap,但对于较小的集合更节省内存。
(http://developer.android.com/reference/android/util/SparseArray.html)
注意不要阻塞Messenger的线程。 Messenger 在单线程中运行,如果你从 handleMessage() 中阻塞,它将阻塞所有其他消息并导致死锁问题。