`
jgsj
  • 浏览: 960637 次
文章分类
社区版块
存档分类
最新评论

Android AsyncChannel源码分析

 
阅读更多

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);
	}
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics