Android的进程间通信(二) 之 AIDL 通信 之 Messenger

Android 常见的几种进程间通信

在Android中,存在着很多种进程间通信。一般而言,Activity之间、广播是通过Intent传输数据的。Service与Activity之间是通过AIDL。其他例如文件通信,用得比较少,实时性差。

Intent 通信几乎和进程内通信的方式一样,没有什么特别之处。所以今天我们来梳理一下AIDL以及AIDL的封装messenger。

用法

预备知识:

  • 如何启动Service?
    启动Service有两种方式,一种是startService,一种是bindService。startService只能通过广播进行进程间通信。而bindService会返回一个远程接口,可调用者调用
Messenger通信

在这里插入图片描述
简单来说,就是把IBinder接口,用Messenger进行包装。在服务端,为了解决线程安全性的问题,用Handle进行串行处理。

Messenger在服务端接收时,是用Handle接收的,会给新手一个假象是:Handle可以跨进程通信。
对于新手,要警惕别人来问一个问题是:Handle机制的三剑客(Looper、MessageQueue、Handle)都没有跨进程的能力,为什么服务端可以用Handle来接收呢?

不要急,不要急,我们来分析一下Messenger的源码。

来看一下客户端。
在得到IBinder接口后,会进行IBinder封装。

Messenger messenger = new Messenger(service);

然后,要进行数据的发送,可以通过send方法发送一个Message给客户端:

messenger.send(Message.obtain(null,MSG_SAY_HELLO,0,0));

我们看一下Messenger.send里面做了什么。

public void send(Message message) throws RemoteException {
    mTarget.send(message);
}

send方法里调用mTarget.send,mTarget是一个IMessenger对象。在Messenger的构造方法里进行初始化,看一下构造方法。

public Messenger(IBinder target) {
    mTarget = IMessenger.Stub.asInterface(target);
}

可以看到 mTarget 从 IMessenger.Stub.asInterface 中来,如果是有用过AIDL的同学看到这里应该很明白了,在使用的AIDL的时候,客户端拿到IBinder接口后,需要调用AIDL的自动生成的代码转化一下接口。
所以,Messenger的客户端,其实基于AIDL,并且Messenger有一个send方法可以进行远程通信。

来看一下服务端
服务端在onBind方法,把服务端的远程接口返回去了。

@Override
public IBinder onBind(Intent intent) {
    mMessenger = new Messenger(new IncomingHandler(this));
    return mMessenger.getBinder();
}

只不过,是先创建Messenger对象,然后通过getBinder得到远程接口。
先看下Messenger(Handle handle)这个构造方法。

public Messenger(Handler target) {
    mTarget = target.getIMessenger();
}

可以看到,在构造方法里,初始化了mTarget对象。mTarget对象是一个IMessenger接口,通过分析Handle.getIMessenger可以知道具体实现是MessengerImpl。看一下MessengerImpl这个类。

private final class MessengerImpl extends IMessenger.Stub {
    public void send(Message msg) {
        msg.sendingUid = Binder.getCallingUid();
        Handler.this.sendMessage(msg);
    }
}

MessengerImpl 类很简单,继承IMessenger.Stub,有一个send方法的定义。学习过AIDL的同学看到这里已经明白了,Messenger的服务端实现也是基于AIDL。因为服务端在使用AIDL时,是需要继承Stub的。

所以,当客户端调用send方法时,数据会经过Binder驱动,AIDL解析之后调用服务端的send方法。在服务端的send方法中,会进行一个数据的串行处理,使之线程安全。

分析完客户端给服务器发送消息的流程,那么有同学一定有疑问是:服务端如何回消息呢?这里就不演示啦,具体做法如下:

如果需要服务端回复,可把客户端也创建一个Messender并且也放入message中,服务端在获取到客户端的Messender然后发送回来即可

好了,Messenger的分析就到此,下一篇将分析Messenger的底层实现AIDL的使用方式以及java层的代码分析。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值