为了更好的理解bound service利用Messenger来夸进程服务,这里先写一篇文章简单分析下Messenger、Handler、Message、Binder的关系。
先来看看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.
Messenger关联一个可以发送消息的Handler。通过指定一个Handler对象创建一个Messenger可以实现基于消息的夸进程通信。
你可以把Messenger理解成一个送信人,他唯一的职责就是送信,即:send(Message msg),来看看send(Message msg)的实现:发送消息的方法:
public void send(Message message) throws RemoteException { mTarget.send(message); }
焦点关注到mTarget, 看看它是什么东西? send方法又是怎么回事? 和handler有关系?
其实Messenger的源码很简单,只有一个成员变量:mTarget(IMessenger的一个实例),核心就是它了,mTarget在构造方法中产生。
两个构造方法:
public Messenger(Handler target) { mTarget = target.getIMessenger(); } public Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target); }
先来说说第一个构造方法(第二个构造方法也许你有些疑惑先放一边,后面解释)。
我们发现,Handler有个getIMessenger()。来看看源码实现:
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) { msg.sendingUid = Binder.getCallingUid(); Handler.this.sendMessage(msg); } }
看到这里,我们发现 mTarget 是一个在Handler中的实现的IMessenger实例(IMessenger.Stub 是IMessenger的实现类,里面实现了n多方法,这里不做深究),里面实现了send方法,这个方法调用了Handler的sendMessage方法。看到这里豁然开朗了吧。 mTarget.send(message);其实最终就是Handler。
看到这里,Messenger和Handler的关系很明显了,即: Messenger利用Handler发送消息 。
上面还有个疑问,第二个构造方法是怎么回事?
public Messenger(IBinder target) { mTarget = IMessenger.Stub.asInterface(target); }
Create a Messenger from a raw IBinder, which had previously been retrieved getBinder。
这是官方解释,即, 通过IBinder创建一个Messenger,这个IBinder必须是之前存在的从getBinder()方法中获取的对象 。
public IBinder getBinder() { return mTarget.asBinder(); }
我们把这两个方法放在一起 ,你会发现mTarget(IMessenger)和IBinder存在转化关系,即IMessenger.Stub已经帮我们实现了这种转化方法 asInterface(),IBinder-》mTarget;asBinder(),mTarget-》IBinder。 所以结论是:IBinder可以关联到一个Handler,通过一个Messenger的getBinder()获取的IBinder可以创建一个关联相同Handler的Messager。
Messenger和Message的关系?
Message 有个成员:replyTo,它是一个Messenger的实例,它有什么作用呢?我们来看一个例子,在这个例子中我们实现两个线程利用Messenger通信。
一个类:MessengerThread
public class MessengerThread extends Thread { private Handler inComingHandler = new Handler() { @Override public void dispatchMessage(Message msg) { Log.d("MessengerThread",msg.obj.toString()); try { Message reMsg = Message.obtain(); reMsg.replyTo = MessengerThread.this.getMessenger(); reMsg.obj = "reply:hello ,am "+getName(); msg.replyTo.send(reMsg); } catch (RemoteException e) { e.printStackTrace(); } } };; private Messenger messenger; private MessengerThread another; public MessengerThread(String name) { super(name); messenger = new Messenger(inComingHandler); } public void setAnother(MessengerThread another){ this.another = another; } public Messenger getMessenger(){ return messenger; } @Override public void run() { if (another != null){ Message msg = Message.obtain(); msg.replyTo = another.getMessenger(); msg.obj = "hello i am "+getName(); try { another.getMessenger().send(msg); } catch (RemoteException e) { e.printStackTrace(); } } super.run(); } }
测试代码:
MessengerThread messengerThreadA = new MessengerThread("A"); MessengerThread messengerThreadB = new MessengerThread("B"); messengerThreadA.setAnother(messengerThreadB); messengerThreadB.setAnother(messengerThreadA); messengerThreadB.start(); messengerThreadA.start();
输出:
949-6949/com.demo.liuguangli.messenger D/MessengerThread﹕ reply:hello ,am A 10-11 16:22:36.573 6949-6949/com.demo.liuguangli.messenger D/MessengerThread﹕ reply:hello ,am B 10-11 16:22:36.573 6949-6949/com.demo.liuguangli.messenger D/MessengerThread﹕ reply:hello ,am A 10-11 16:22:36.574 6949-6949/com.demo.liuguangli.messenger D/MessengerThread﹕ reply:hello ,am B
demo地址: https://github.com/liuguangli/MessengerDemo