Android Messenger 分析

我们直接看源码:

/**
 * Reference to a Handler, which others can use to send messages to it.
 * This allows for the implementation of message-based communication across
 * processes, by creating a Messenger pointing to a Handler in one process,
 * and handing that Messenger to another process.
 */
public final class Messenger implements Parcelable {
    private final IMessenger mTarget;

    /**
     * Create a new Messenger pointing to the given Handler.  Any Message
     * objects sent through this Messenger will appear in the Handler as if
     * {@link Handler#sendMessage(Message) Handler.sendMessage(Message)} had
     * been called directly.
     * 
     * @param target The Handler that will receive sent messages.
     */
    public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }
Messenger,信使,其指向一个Handler,他人可以使用信使向Handler发送消息。信使实现了基于消息队列的跨进程的通讯,在一个进程中创建一个指向Handler的信使,然后把信使返回给其他的进程,使得其它的进程可以向这个进程发送消息。在Messenger内部有一个IMessenger接口指针,其在Messenger的构造函数中指向了一个Handler中的IMessenger,这样就保存了一个指向Handler的指针。

我们再来看一下Handler是怎么返回一个IMessenger接口的实现的:

    final IMessenger getIMessenger() {
        synchronized (mQueue) {
            if (mMessenger != null) {
                return mMessenger;
            }
            mMessenger = new MessengerImpl();
            return mMessenger;
        }
    }

    private final class MessengerImpl extends IMessenger.Stub {
        public void send(Message msg) {
            Handler.this.sendMessage(msg);
        }
    }
我们看到在getIMessenger方法内部对消息队列进行加锁,是为了确保一个消息队列只有一个信使,这个有点类似实现单例时也要加锁一样。IMessenger接口指向一个私有内部类MessengerImpl,其 send方法内部使用Handler.this.sendMessage方法。

    /**
     * Send a Message to this Messenger's Handler.
     * 
     * @param message The Message to send.  Usually retrieved through
     * {@link Message#obtain() Message.obtain()}.
     * 
     * @throws RemoteException Throws DeadObjectException if the target
     * Handler no longer exists.
     */
    public void send(Message message) throws RemoteException {
        mTarget.send(message);
    }
再来看Messenger中的send方法,其调用IMessenger接口的send方法,所以最终是调用了Handler中的sendMessage方法。

从一个作为服务器的Service中返回一个Messenger给调用的客户端是怎么做到的呢?

	/**
	 * When binding to the service, we return an interface to our messenger for
	 * sending messages to the service.
	 */
	@Override
	public IBinder onBind(Intent intent) {
		return mMessenger.getBinder();
	}
看Android developer官网关于 Messenger的例子

在一个客户端绑定到一个服务器的时候,我们返回Messenger.getBinder()的结果。其实现如下:

    /**
     * Retrieve the IBinder that this Messenger is using to communicate with
     * its associated Handler.
     * 
     * @return Returns the IBinder backing this Messenger.
     */
    public IBinder getBinder() {
        return mTarget.asBinder();
    }
其中的mTarget就是IMessenger接口的asBinder()方法,其实际调用 IMessenger.Stub.asBinder方法。

在一个客户端与服务器进行连接的时候,其会建立对Messenger的引用:

		public void onServiceConnected(ComponentName className, IBinder service) {
			// This is called when the connection with the service has been
			// established, giving us the service object we can use to
			// interact with the service. We are communicating with our
			// service through an IDL interface, so get a client-side
			// representation of that from the raw service object.
			mService = new Messenger(service);
			mCallbackText.setText("Attached.");

			// We want to monitor the service for as long as we are
			// connected to it.
			try {
				Message msg = Message.obtain(null,
						MessengerService.MSG_REGISTER_CLIENT);
				msg.replyTo = mMessenger;
				mService.send(msg);

				// Give it some value as an example.
				msg = Message.obtain(null, MessengerService.MSG_SET_VALUE,
						this.hashCode(), 0);
				mService.send(msg);
			} catch (RemoteException e) {
				// In this case the service has crashed before we could even
				// do anything with it; we can count on soon being
				// disconnected (and then reconnected if it can be restarted)
				// so there is no need to do anything here.
			}

			// As part of the sample, tell the user what happened.
			Toast.makeText(Binding.this, R.string.remote_service_connected,
					Toast.LENGTH_SHORT).show();
		}
其调用Messenger另一个构造方法:

    /**
     * Create a Messenger from a raw IBinder, which had previously been
     * retrieved with {@link #getBinder}.
     * 
     * @param target The IBinder this Messenger should communicate with.
     */
    public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
    }
把IBinder接口转化为IMessenger接口,这样就在客户端的代码中引用了服务器的Messenger,之后就是想向服务器发什么消息就发什么消息了。

那么服务器怎么向客户端发消息呢?总不能只有客户端发命令给服务器吧。双向通讯才是关键。

				Message msg = Message.obtain(null,
						MessengerService.MSG_REGISTER_CLIENT);
				msg.replyTo = mMessenger;
				mService.send(msg);
一个客户端向服务器发送的消息里面指定了msg.replayTo=mMessenger;

    /**
     * Optional Messenger where replies to this message can be sent.  The
     * semantics of exactly how this is used are up to the sender and
     * receiver.
     */
    public Messenger replyTo;
一条消息可以指定是由哪个信使来发出的,这样在Handler中收到消息之后就可以调用其引用的信使来发送消息。

	/**
	 * Handler of incoming messages from clients.
	 */
	class IncomingHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MSG_REGISTER_CLIENT:
				mClients.add(msg.replyTo);
				break;
			case MSG_UNREGISTER_CLIENT:
				mClients.remove(msg.replyTo);
				break;
			case MSG_SET_VALUE:
				mValue = msg.arg1;
				for (int i = mClients.size() - 1; i >= 0; i--) {
					try {
						mClients.get(i).send(
								Message.obtain(null, MSG_SET_VALUE, mValue, 0));
					} catch (RemoteException e) {
						// The client is dead. Remove it from the list;
						// we are going through the list from back to front
						// so this is safe to do inside the loop.
						mClients.remove(i);
					}
				}
				break;
			default:
				super.handleMessage(msg);
			}
		}
	}
例如,在上面这个服务器的Handler中收到自己的信使发送的消息之后,把消息中引用的客户端的信使的引用保存到一个集合中,这样就拿到客户端的信使,只要调用其的send方法就可以调用客户端的代码。如此实现了双向通信。

这样一来,服务器可以实现广播、组播、单播消息的功能。

Messenger的接口IMessenger实际是通过AIDL来做的。

文件位于:frameworks/base/core/java/android/os/IMessenger.aidl

看来Handler不仅仅能够用于线程之间的通讯还能用于进程之间的通讯!Handler,Looper,MessageQueue,Message的关系需要深刻理解!








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值