简介
AsyncChannel 双Handler进程通信(同一进程或不同进程)。重点分析不同进程通信的原理
案例
WifiManager 客户端
WifiService 服务端
AsyncChannel属于联系两者的媒介
源码
7.1
补充点
Messenger
CountDownLatch
客户端:WifiManager
1.WifiManager 需要一个Handler ?
private class ServiceHandler extends Handler {
······
public void handleMessage(Message message) {
}
······
}
2.AsyncChannel与Handler建立连接?
private synchronized AsyncChannel getChannel() {
if (mAsyncChannel == null) {
/**
* public Messenger getWifiServiceMessenger() {
* try {
* return mService.getWifiServiceMessenger();
* } catch (RemoteException e) {
* throw e.rethrowFromSystemServer();
* }
* }
*/
Messenger messenger = getWifiServiceMessenger();//获取的是目的地的Messenger。即服务端的Handler
mAsyncChannel = new AsyncChannel();
Handler handler = new ServiceHandler(mLooper);//客户端的Handler
mAsyncChannel.connect(mContext, handler, messenger);//将客户端和服务端的Handler建立连接
}
return mAsyncChannel;
}
3.怎么知道连接成功?
流程:
1)AsynChannel通知WifiManager.ServiceHandler:CMD_CHANNEL_HALF_CONNECTED
2)WifiManager.ServiceHandler再通过AsynChannel告知服务端
a.查看AsyncChannel的api
void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger)
AsyncChannel.java
public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("connect srcHandler to the dstMessenger E");
// We are connected
connected(srcContext, srcHandler, dstMessenger);
// Tell source we are half connected
replyHalfConnected(STATUS_SUCCESSFUL);
if (DBG) log("connect srcHandler to the dstMessenger X");
}
片段1:connected
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;
linkToDeathMonitor();//怎么知道服务端的对象不存在呢?linkToDeathMonitor就是监听的方法
if (DBG) log("connected srcHandler to the dstMessenger X");
}
片段2:replyHalfConnected
private void replyHalfConnected(int status) {
Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_HALF_CONNECTED);
msg.arg1 = status;
msg.obj = this;
msg.replyTo = mDstMessenger;
if (!linkToDeathMonitor()) {
// Override status to indicate failure
msg.arg1 = STATUS_BINDING_UNSUCCESSFUL;
}
mSrcHandler.sendMessage(msg);//AsyncChannel发消息给客户端Handler,并带上服务端Handler(msg.replyTo = mDstMessenger)
}
b.WifiManager.ServiceHandler通过AsynChannel告知服务端:CMD_CHANNEL_FULL_CONNECTION
private void dispatchMessageToListeners(Message message) {
······
switch (message.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
}
······
}
查看AsyncChannel的api
void sendMessage(int what)
public void sendMessage(int what) {
Message msg = Message.obtain();
msg.what = what;
sendMessage(msg);
}
public void sendMessage(Message msg) {
msg.replyTo = mSrcMessenger;
try {
mDstMessenger.send(msg);//服务端的Handler发送数据
} catch (RemoteException e) {
replyDisconnected(STATUS_SEND_UNSUCCESSFUL);
}
}
4.小结
AsyncChanel处理Handler跨进程通信的细节
1)AsyncChannel对象包含两个变量:mSrcMessenger、mDstMessenger
2)消息分发:
a.客户端处理CMD_CHANNEL_HALF_CONNECTED
b.服务端处理CMD_CHANNEL_FULL_CONNECTION
服务端WifiService(实现类:WifiServiceImpl)
1.WifiServiceImpl 需要一个Handler ?
private class ClientHandler extends Handler {
······
public void handleMessage(Message message) {
}
······
}
2.AsyncChannel与Handler建立连接?
public Messenger getWifiServiceMessenger() {
enforceAccessPermission();
enforceChangePermission();
return new Messenger(mClientHandler);
}
3.服务端接收到CMD_CHANNEL_FULL_CONNECTION怎么处理?
private class ClientHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
// We track the clients by the Messenger
// since it is expected to be always available
mTrafficPoller.addClient(msg.replyTo);
} else {
Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
}
break;
}
····
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
AsyncChannel ac = new AsyncChannel();
ac.connect(mContext, this, msg.replyTo);//服务端重新创建了一个AsyncChannel对象,将客户端的handler放在mTrafficPoller中
break;
}
···
}
}
}
总结
1.AsyncChannel处理双Handler进程间通信,核心在于Messenger承载了Handler
2.客户端和服务端,各自拿了一个AsyncChannel对象,通过connect建立连接
其他
AsyncChannel仍有很多其他好玩的API,例如:
public void connect(AsyncService srcAsyncService, Messenger dstMessenger)
AsyncService继承Service,封装中包裹一个Handler
public void connect(Context srcContext, Handler srcHandler, String dstPackageName,
String dstClassName)
dstClassName是一个Service,binder需要继承IMessenger.Stub
public Message sendMessageSynchronously(Message msg)
消息同步处理,即消息发送出去等服务端处理完成后才有结果。
涉及算法知识栈类:Stack
等等等等
知识点
Messenger
概述
Messenger implements Parcelable,可跨进程传递数据
接口分析
public final class Messenger implements Parcelable {
private final IMessenger mTarget;
public Messenger(Handler target) {//传入Handler的构造方法
mTarget = target.getIMessenger();
}
······
public Messenger(IBinder target) {//传入IBinder的构造方法
mTarget = IMessenger.Stub.asInterface(target);
}
}
补充
Handler类自带Messenger变量
android.os.Handler:
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}
场景
1.如果远程的对象死了,怎么知道?
Binder有一种linkToDeath机制
mDstMessenger.getBinder().linkToDeath(mDeathMonitor, 0);
2.WifiManager在使用AsyncChannel时,对于connect的回调方法,怎么进行监听?
a.采用了一种很巧妙的方法
b.SparseArray mListenerMap = new SparseArray();
仅仅将int值传给服务端,服务端传过来,在列表中查找对应的监听对象
网友评论