Messenger的作用就是在不同进程中通过Message对象进行通信。Messenger 的创建直接new 就可以,其中构造方法有两个,一个是传入Handler 一个是传入IBinder ,传入Handler 是服务端接收消息用的构造方法,传入IBinder 是客户端用来发送消息的构造方法。我们可以从Messenger的两个构造方法中看出,Messenger 的内部实现和AIDL 是相同的,Messenger是基于AIDL 模式 实现的,Messenger 其实就是对AIDL 又进行一次封装。
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
这个是服务端接收消息的构造方法。Handler.getIMessenger()方法直接回获取一个IMessenger 对象,这个方法里面是这样的
final IMessenger getIMessenger() {
synchronized (mQueue) {
if (mMessenger != null) {
return mMessenger;
}
mMessenger = new MessengerImpl();
return mMessenger;
}
}可以出如果有mMessenger 直接返回,没有就创建一个MessengerImpl 实例类进行返回。 MessengerImpl 继承了IMessenger.Stub ,和AIDL 中的Stub一样。(内部的结构和AIDL 生成的一样,也有Proxy代理类)。
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
这个是客户端的构造方法,为什么要传递IBinder呢?这个IBinder 其实就是服务端的Messenger(内部实现的MessengerImpl),通过代理类去调用方法send 中的mRemote.transact(Stub.TRANSACTION_send, _data, null, // 接收的code和发送的code都是TRANSACTION_sendIBinder.FLAG_ONEWAY)方法和之前的AIDL 文件一模一样,没什么好说的,在transact 中调用ontransact 把数据传递到服务端,然后在ontransact 方法里面发送这个Message 到服务端的Handler内部中处理!。下面上服务端的代码
public class MessengerService extends Service {
private final static String TAG = "MessengerService";
@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}
private static class MessengerHandle extends Handler{
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case MyConstants.MSG_FROM_CLIENT:
Log.e(TAG,"receive msg from Client:" + msg.getData().getString("msg"));
break;
default:
super.handleMessage(msg);
}
}
}
private final Messenger messenger = new Messenger(new MessengerHandle());
}非常简单吧。只是内部比较麻烦而以。多想多思考就行了。
这个是客户端的
public class MainActivity extends AppCompatActivity {
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Messenger messenger = new Messenger(service);
Message obtain = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("msg","Hello,this is Client");
obtain.setData(bundle);
try {
messenger.send(obtain);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, MessengerService.class);
bindService(intent,connection,BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
unbindService(connection);
super.onDestroy();
}
} 注意了。客户端的 messenger.send(obtain); 这行代码和服务端的调用不是同一个方法哦!客户端的Messenger 是Proxy 的执行的是mRemote.transact核心代码。服务端的是Stub 里面的执行的是MessengerImpl 里面的Handler.this.sendMessage方法(MessengerImpl 是Handler的内部类)。 总结一下就是客户端通过把服务端的Binder 带到 自己的proxy 内部中作为全局变量保存起来。并且执行transact 方法,将data 客户端数据传递到服务端,服务端stub 中重写binder的onTransact方法接手到data, 进行解析创建message 将信息怎么来的,怎么存回去。最后通过Handler.this.sendMessage方法 发送到消息队列,服务端取出message.
在这里需要注意的是,我这篇博客写的阅读应用层Binder 和Messenger的具体内部代码,而且不是讲的原理,如果想要知道在什么时候客户端的Service 和服务端的ServiceManage 进行跨进程的连接,并且又如何映射的虚拟内存,在Binder 驱动层。那么我们就需要去从Context.BindService 方法中去进一步的查阅。不过,个人不推荐初学者尝试,有可能进去了走不出来,还浪费时间,还是希望大家多掌握一点基础知识 各种设计模式之后才去看这些比较复杂的结构源码。
今天就分享这么多谢谢大家。