AsyncChannel类用于处理两个Handler之间的异步消息传递,消息传递的Handler可以出于同一进程,也可以处于不同进程,不同进程之间的Handler消息传递使用Android的Binder通信机制来实现。
1.同一进程间的Handler连接
fullyConnectSync函数建立的是进程内的Handler通信
public int fullyConnectSync(Context srcContext, Handler srcHandler, Handler dstHandler) {
int status = connectSync(srcContext, srcHandler, dstHandler);
if (status == STATUS_SUCCESSFUL) {
Message response = sendMessageSynchronously(CMD_CHANNEL_FULL_CONNECTION);
status = response.arg1;
}
return status;
}
public int connectSync(Context srcContext, Handler srcHandler, Handler dstHandler) {
return connectSync(srcContext, srcHandler, new Messenger(dstHandler));
}
public int connectSync(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("halfConnectSync srcHandler to the dstMessenger E");
connected(srcContext, srcHandler, dstMessenger);
if (DBG) log("halfConnectSync srcHandler to the dstMessenger X");
return STATUS_SUCCESSFUL;
}
public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("connected srcHandler to the dstMessenger E");
// Initialize source fields
mSrcContext = srcContext;
mSrcHandler = srcHandler;
mSrcMessenger = new Messenger(mSrcHandler);
// Initialize destination fields
mDstMessenger = dstMessenger;
if (DBG) log("connected srcHandler to the dstMessenger X");
}
对于同一进程的handler 通信,如果与连接相关的对象初始化完成了,那就说明双方的连接是没有问题了。如果连接成功就发送 CMD_CHANNEL_FULL_CONNECTION消息,这个消息被发送到 AsyncChannel中的 SyncMessenger,SyncMessenger维护着一个消息栈和消息发送线程。
2.不同进程间的Handler连接
public void connect(Context srcContext, Handler srcHandler, String dstPackageName,
String dstClassName) {
if (DBG) log("connect srcHandler to dst Package & class E");
//启动一个连接线程
ConnectAsync ca = new ConnectAsync(srcContext, srcHandler, dstPackageName, dstClassName);
new Thread(ca).start();
if (DBG) log("connect srcHandler to dst Package & class X");
}
启动ConnectAsync线程后,执行该线程中的run方法
final class ConnectAsync implements Runnable {
Context mSrcCtx;
Handler mSrcHdlr;
String mDstPackageName;
String mDstClassName;
@Override
public void run() {
int result = connectSrcHandlerToPackageSync(mSrcCtx, mSrcHdlr, mDstPackageName,
mDstClassName);
replyHalfConnected(result);
}
}
直接调用connectSrcHandlerToPackageSync函数来实现跨进程Handler连接
public int connectSrcHandlerToPackageSync(
Context srcContext, Handler srcHandler, String dstPackageName, String dstClassName) {
if (DBG) log("connect srcHandler to dst Package & class E");
mConnection = new AsyncChannelConnection();
/* Initialize the source information */
mSrcContext = srcContext;
mSrcHandler = srcHandler;
mSrcMessenger = new Messenger(srcHandler);
mDstMessenger = null;
/* Send intent to create the connection */
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(dstPackageName, dstClassName);
//通过绑定服务来实现不同进程间的Handler连接
boolean result = srcContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
if (DBG) log("connect srcHandler to dst Package & class X result=" + result);
return result ? STATUS_SUCCESSFUL : STATUS_BINDING_UNSUCCESSFUL;
}
AsyncChannelConnection实现了ServiceConnection接口,在服务成功连接上时,自动调用onServiceConnected函数
class AsyncChannelConnection implements ServiceConnection {
AsyncChannelConnection() {
}
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
mDstMessenger = new Messenger(service);
replyHalfConnected(STATUS_SUCCESSFUL);
}
@Override
public void onServiceDisconnected(ComponentName className) {
replyDisconnected(STATUS_SUCCESSFUL);
}
}
3. 消息同步发送
AsyncChannel提供了sendMessageSynchronously消息同步发送接口,该函数由AsyncChannel的内部类SyncMessenger实现
public Message sendMessageSynchronously(int what) {
Message msg = Message.obtain();
msg.what = what;
Message resultMsg = sendMessageSynchronously(msg);
return resultMsg;
}
public Message sendMessageSynchronously(Message msg) {
Message resultMsg = SyncMessenger.sendMessageSynchronously(mDstMessenger, msg);
return resultMsg;
}
直接调用内部类SyncMessenger的成员sendMessageSynchronously函数来发送一个同步消息
private static Message sendMessageSynchronously(Messenger dstMessenger, Message msg) {
//获取一个SyncMessenger对象
SyncMessenger sm = SyncMessenger.obtain();
try {
if (dstMessenger != null && msg != null) {
msg.replyTo = sm.mMessenger;
synchronized (sm.mHandler.mLockObject) {
//发送消息
dstMessenger.send(msg);
//等待回复
sm.mHandler.mLockObject.wait();
}
} else {
sm.mHandler.mResultMsg = null;
}
} catch (InterruptedException e) {
sm.mHandler.mResultMsg = null;
} catch (RemoteException e) {
sm.mHandler.mResultMsg = null;
}
//得到返回的消息,消息是从SyncHandler的handleMessage函数中返回来的
Message resultMsg = sm.mHandler.mResultMsg;
sm.recycle();
return resultMsg;
}
SyncMessenger是用来发送同步消息的,通过 sendMessageSynchronously()方法发送消息,并调用了object类的wait方法等待目的handler收到消息后,取出消息中的replyto,然后再用该messenger给SyncMessenger类中的SyncHandler发送消息在该handler的handleMessage方法里面才执行object的notify方法,以保证发送消息的同步性。使用SyncMessenger的静态函数obtain来获取一个SyncMessenger实例。
private static SyncMessenger obtain() {
SyncMessenger sm;
synchronized (sStack) {
if (sStack.isEmpty()) {
//创建SyncMessenger对象
sm = new SyncMessenger();
//创建具有消息循环队列的HandlerThread线程,并启动该线程
sm.mHandlerThread = new HandlerThread("SyncHandler-" + sCount++);
sm.mHandlerThread.start();
//创建SyncHandler对象
sm.mHandler = sm.new SyncHandler(sm.mHandlerThread.getLooper());
sm.mMessenger = new Messenger(sm.mHandler);
} else {
sm = sStack.pop();
}
}
return sm;
}
SyncMessenger作为一个辅助类,包含了一个线程HandlerThread 的实例mHandlerThread、处理msg的类SyncHandler(Handler的子类)的实例mHandler、接收msg的Messenger实例mMessenger。也就是说,发送给Messenger的消息msg将由SyncHandler来处理,这个处理过程运行在线程HandlerThread中。
同步发送机制:调用者利用SyncMessenger的成员sendMessageSynchronously将要发送的消息msg送往dstMessenger所在的目的进程,由dstMessenger的handler进行处理,然后消息发送线程等待,dstMessenger的handler处理完毕接收到的消息后,要向msg.replyTo回送消息,这时由SyncHandler的handleMessage来处理该回复消息,它将唤醒在消息发送线程中等待的sendMessageSynchronously。从目的进程返回的msg在SyncHandler的handleMessage中拷贝给SyncHandler的mResultMsg,然后由sendMessageSynchronously返回给调用者。
4.消息异步发送
public void sendMessage(int what, int arg1, int arg2, Object obj) {
Message msg = Message.obtain();
msg.what = what;
msg.arg1 = arg1;
msg.arg2 = arg2;
msg.obj = obj;
sendMessage(msg);
}
public void sendMessage(Message msg) {
msg.replyTo = mSrcMessenger;
try {
mDstMessenger.send(msg);
} catch (RemoteException e) {
replyDisconnected(STATUS_SEND_UNSUCCESSFUL);
}
}