Messenger是什么
Messenger是Android提供的一种跨进程通讯方式,可以实现两个进程之间的数据消息传递。
为什么Messenger可以跨进程通信
因为AIDL是Android提供给我们的标准跨进程通讯API,而Messenger则是官方基于AIDL的一层封装,是一种轻量级的进程间通讯方式,可以在进程之间传递Message对象,我们在Message中放入需要传递的数据即可轻松实现进程间通讯。
Messenger基于AIDL这点可以通过它的构造方法得知,用过AIDL的小伙伴应该对Stub和asInterface()这个方法不陌生,这个方法返回了AIDL接口对象供我们调用实现进程通讯。
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
那么接着往下发现两个构造方法都实现了对mTarget的赋值,那么这个mTarget又是什么?
private final IMessenger mTarget;
阅读源码得知mTarget是一个IMessage实例,到此有些小伙伴可能推测出IMessenger就是官方定义的AIDL接口了,mTarget通过Messenger的构造方法初始化,那么通过Binder获取AIDL接口是没问题,可是另一个传入Handler的构造是怎么回事?点进Handler的源码去看看。
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);
}
}
Handler内创建了私有内部类MessengerImpl继承了IMessage.Stub类实现了send()方法,并通过getIMessage()方法获取其实例对象,用过AIDL的同学看到IMessenger.Stub肯定不陌生,这个Stub类是IMessenger的静态内部类,其继承Binder类并实现了IMessenger接口,send()方法就是IMessenger接口中定义的。
send()方法内部实现就两行代码,send()方法接收一个Message对象,并将客户端(调用进程)的Uid设置给Message对象,这样服务端(接收进程)就可以通过msg.sendingUid知道Message是哪个进程发送过来的,接着客户端通过Handler的sendMessage()方法将Message发送给服务端实现数据消息通讯,看到Handler,意味着Messenger和进程之间的消息处理是串行的,不会有线程同步的问题,因此在有并行处理的需求下Messenger就不适用了。
使用Messenger向服务端通信
示例通过App进程当做客户端,MessengerService服务当做服务端使用Messenger进行跨进程通讯。
我们需要进行以下步骤来实现使用Messenger进行进程间通讯
- 服务实现一个
Handler
,由该类为每个客户端调用接收回调。 - 服务使用
Handler
来创建Messenger
对象。 Messenger
创建一个IBinder
,服务通过onBind()
使其返回客户端。- 客户端在onServiceConnected()中使用
IBinder
将Messenger
实例化,然后使用后者将Message
对象发送给服务。 - 服务在其
Handler
中(是在handleMessage()
方法中)接收每个Message并做处理
。
服务端
class MessengerService : Service() {
@SuppressLint("HandlerLeak")
inner class ServiceHandler : Handler() {
override fun handleMessage(msg: Message?) {
//打印客服端发来的内容
Log.d("kkk",msg.data.getSerializable("data").toString())
}
}
private val mMessenger = Messenger(ServiceHandler())
override fun onBind(intent: Intent?): IBinder? {
return mMessenger.binder
}
}
客户端
class MessengerActivity : AppCompatActivity() {
//服务端Messenger
private var mServiceMessenger: Messenger? = null
private val mServiceConnection = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
mServiceMessenger = null
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
mServiceMessenger = Messenger(service)
//向服务端发送数据
msg = Message.obtain().also {
val bundle = Bundle()
bundle.putSerializable("data", SimpleData("客户端", "服务端"))
it.data = bundle
}
mServiceMessenger?.send(msg)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_messenger)
//绑定服务
bindService.setOnClickListener {
Intent(this, MessengerService::class.java).also {
bindService(it, mServiceConnection, Context.BIND_AUTO_CREATE)
}
}
}
}
class SimpleData(private val from: String, private val to: String):Serializable {
override fun toString(): String {
return "这是一条从${from}发往${to}的消息"
}
}
客户端通过bindService()方法绑定服务,并通过在onServiceConnected()中服务在onBind()中返回的binder对象拿到服务端的Messenger对象,通过它我们就可以向服务端发送Message对象进行通讯。
使用Messenger向客户端通信
上面的过程实现了不同进程的客户端向服务端的单方面通讯,那么服务端如何向客户端通讯实现双向通讯呢?
1.客户端实现一个Handler,由该类为服务端调用接收回调。
2.客户端使用Handler创建Messenger对象。
3.通过设置Message的replyTo字段将客户端Messenger对象用服务端Messenger对象发送给服务端。
4.服务端通过接收到的Message对象拿到客户端的Messenger对象,使用其将Message对象发送给客户端。
5.客户端在其 Handler
中(是在 handleMessage()
方法中)接收每个 Message并做处理
。
对上面的例子进行一番改造
服务端
class MessengerService : Service() {
companion object {
//服务注册客户端
const val MSG_REGISTER_CLIENT = 1
//服务解除客户端
const val MSG_UNREGISTER_CLIENT = 2
//客户端传递数据
const val MSG_SET_VALUE = 3
}
//管理注册进来的客户端集合
private val mClients = arrayListOf<Messenger>()
@SuppressLint("HandlerLeak")
inner class ServiceHandler : Handler() {
override fun handleMessage(msg: Message?) {
when (msg?.what) {
MSG_REGISTER_CLIENT -> {
mClients.add(msg.replyTo)
}
MSG_UNREGISTER_CLIENT -> {
mClients.remove(msg.replyTo)
}
MSG_SET_VALUE -> {
mClients.forEach {
try {
Log.d("kkk",msg.data.getSerializable("data").toString())
//收到客户端发来的消息后也向客户端发送一条消息
val message = obtainMessage(MSG_SET_VALUE)
val bundle = Bundle()
bundle.putSerializable("data", SimpleData("服务端", "客户端"))
message.data = bundle
it.send(message)
} catch (e: RemoteException) {
mClients.remove(it)
}
}
}
else -> super.handleMessage(msg)
}
}
}
private val mMessenger = Messenger(ServiceHandler())
override fun onBind(intent: Intent?): IBinder? {
Log.i("kkk", "绑定服务")
return mMessenger.binder
}
}
客户端
class MessengerActivity : AppCompatActivity() {
//客户端Messenger
private val mClientMessenger = Messenger(ClientHandler())
//服务端Messenger
private var mServiceMessenger: Messenger? = null
private var mIsBound = false
//客户端Messenger所需Handler
@SuppressLint("HandlerLeak")
inner class ClientHandler : Handler() {
@SuppressLint("SetTextI18n")
override fun handleMessage(msg: Message?) {
when (msg?.what) {
//打印服务端返回的数据
MessengerService.MSG_SET_VALUE -> {
service_status.text = msg.data.getSerializable("data").toString()
}
else -> super.handleMessage(msg)
}
}
}
private val mServiceConnection = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
mServiceMessenger = null
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
mServiceMessenger = Messenger(service)
//向服务端注册客户端
var msg = Message.obtain(null, MessengerService.MSG_REGISTER_CLIENT)
msg.replyTo = mClientMessenger
mServiceMessenger?.send(msg)
//向服务端发送数据
msg = Message.obtain(null, MessengerService.MSG_SET_VALUE).also {
val bundle = Bundle()
bundle.putSerializable("data", SimpleData("客户端", "服务端"))
it.data = bundle
}
mServiceMessenger?.send(msg)
mIsBound = true
service_status.text = "服务已绑定"
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_messenger)
//绑定服务
bindService.setOnClickListener {
Intent(this, MessengerService::class.java).also {
bindService(it, mServiceConnection, Context.BIND_AUTO_CREATE)
}
}
}
override fun onDestroy() {
super.onDestroy()
//注销服务
if (mIsBound){
//解除在服务端注册的客户端
val msg = Message.obtain(null, MessengerService.MSG_UNREGISTER_CLIENT)
msg.replyTo = mClientMessenger
mServiceMessenger?.send(msg)
unbindService(mServiceConnection)
}
}
}
Messenger的优缺点
优点:
- 使用简单,不需要自己实现AIDL接口
- 线程安全,不需要处理线程同步问题
缺点:
- 只能传递数据,不能直接调用方法
- 因为使用Handler,所以不支持并发操作
远程调用的阻塞与非阻塞
关于远程调用阻塞调用方线程的问题可以查看这篇博文
总结
本来这篇博客可有可无,但是有些知识久不用了就容易忘记,还是这种平时接触比较少的知识,索性还是趁着明白的时候记录一下,日后若忘记了还可以温故而知新,说不定还能帮助一些需要用它的人。总的来说Messenger还是比较简单的,只是官方对于AIDL的一层封装,隐去了AIDL的实现细节,方便我们使用,不算难懂的知识,对于跨进程感兴趣的同学还是应把AIDL和Binder机制搞清楚才是重点。接下来我可能会再写一篇使用AIDL进行跨进程通讯的文章,至于Binder机制。。。哈哈,就算了,我还没搞清楚,就不写文章误人子弟了。