Messenger是什么?
Messenger
在 Android
中和 AIDL
一样,用于进程间通信的技术,也是基于 AIDL
的封装。
Messenger怎么用?
服务端
服务端需要继承 Service
这个没什么好说的。
在讲 AIDL
的时候,服务端要自己实现 IBinder
并通过 onBind
方法返回给客户端使用。 Messenger
也是类似的,不过就不需要再写 .aidl
文件了。只需要创建一个 Messenger
对象,然后在 onBind
中把 Messenger.binder
给返回出去就行了。
在 Messenger
的构造方法中,需要创建一个 Handler
用来处理客户端发过来的消息,这样我们就可以专注于业务逻辑的开发了。这就有点像线程间通信了,对与不熟悉的人就可以快速上手,学习成本就小多了。
1
2
3
4
5
6
7
8
9
10
11
12
|
class MessengerService : Service() {
val mMessenger = Messenger(object : Handler() {
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
println(msg)
}
})
override fun onBind(intent: Intent?): IBinder? {
return mMessenger.binder
}
}
|
客户端
客户端和 AIDL
一样需要先连接上服务端,然后拿到服务端的 Binder
。
拿到服务端之后需要用 Messenger
包装一下,然后就可以通过 Messenger.send
方法发送消息给服务端了。
当然发送的消息要通过 Message
来传递,也就是 what
、 arg1
、 arg2
、 Bundle
来传递了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
class MainActivity : AppCompatActivity() {
private val TAG = MainActivity::class.simpleName
var mMessenger:Messenger? = null
val conn = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
Log.d(TAG,"onServiceDisconnected")
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
mMessenger = Messenger(service)
sendMsgToServer()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
bindService(Intent(this, MessengerService::class.java), conn, Context.BIND_AUTO_CREATE)
}
fun sendMsgToServer() {
val msg = Message.obtain(null, 1)
mMessenger?.send(msg)
}
}
|
Messenger的原理
我们从服务端看起,在服务端的 onBind
中返回的是 Messenger
中的 binder
1
2
3
4
5
6
7
|
public IBinder getBinder() {
return mTarget.asBinder();
}
public Messenger(Handler target) {
mTarget = target.getIMessenger();
}
|
在 getBinder
中返回的是 mTarget.asBinder
而 mTarget
是从 Handler.getIMessenger
中得到的,跟进去看看
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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);
}
}
|
可以看到返回的是 MessengerImpl
, MessengerImpl
继承 IMessenger.Stub
这个和我们之前讲 AIDL
有些类似,打开 AndroidXRef ,搜索一下 IMessenger.aidl
还真的找到有这个文件 Cross Reference: /frameworks/base/core/java/android/os/IMessenger.aidl ,内容如下
1
2
3
4
5
6
7
8
|
package android.os;
import android.os.Message;
/** @hide */
oneway interface IMessenger {
void send(in Message msg);
}
|
里面只有一个方法 send
这个就是用来发消息的了。有兴趣的可以用 aidl
工具来生成对应的 java
文件。接下来我们来看客户端
1
2
3
4
5
6
|
public Messenger(IBinder target) {
mTarget = IMessenger.Stub.asInterface(target);
}
public void send(Message message) throws RemoteException {
mTarget.send(message);
}
|
在服务端连接成功后,我们通过 Messenger
的构造方法把 IBinder
传递进去,在构造方法里通过 asInterface
转换为服务端的代理对象,使用 send
来和服务端通信,也是唯一的方法。
看到这里也就明白了,其实 Messenger
也是使用的 AIDL
来进行跨进程调用,只不过提供了一层封装,更加容易上手,并且还和 Handler
巧妙的结合起来,使得 Handler
既能处理多线程还能处理多进程。
总结
这样的设计把一个比较复杂的事物用一个我们日常比较熟悉的事物封装可以达到降低学习成本的目的。
需要注意的是 Messenger
只适合一对多的串行通信,并且不能有返回值,不能很好处理高并发场景。
参考