Android跨进程通信之Messenger

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进行进程间通讯

  1. 服务实现一个 Handler,由该类为每个客户端调用接收回调。
  2. 服务使用 Handler 来创建 Messenger 对象。
  3. Messenger 创建一个 IBinder,服务通过 onBind() 使其返回客户端。
  4. 客户端在onServiceConnected()中使用 IBinder 将 Messenger实例化,然后使用后者将 Message 对象发送给服务。
  5. 服务在其 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.通过设置MessagereplyTo字段将客户端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机制。。。哈哈,就算了,我还没搞清楚,就不写文章误人子弟了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值