Android Messenger和Handler的关系

刚开始接触Messenger和Handler时,总感觉他俩有点相似,因为它俩都有“send(Message message)”方法,并且处理消息都是串行的,后来看了源码才知道,它俩何止是相似,Messenger完全就是Handler支持跨进程调用的增强版。

Messenger的基本用法

服务端:MyService.kt

class MyService : Service() {
    val mServiceMessenger = Messenger(ServiceMessengerHandler(Looper.getMainLooper()))

    class ServiceMessengerHandler(looper: Looper) : Handler(looper) {
        override fun handleMessage(msg: Message) {
            val messageString = msg.data.getString("message")
            Log.d("mytestmessenger", "Receive Client message: $messageString")
            val message = Message.obtain()
            val data = Bundle()
            data.putString("message", "hello, I am Service!")
            message.data = data
            msg.replyTo.send(message)
        }
    }

    override fun onBind(intent: Intent?): IBinder? {
        return mServiceMessenger.binder
    }
}

配置文件:AndroidManifest.xml
声明在另一个进程中运行

<service android:name=".MyService"
            android:process=":myService"/> 

客户端:MainActivity.kt

var mClientMessenger = Messenger(ClientMessengerHandler(Looper.getMainLooper()))

class ClientMessengerHandler(looper: Looper) : Handler(looper) {
	override fun handleMessage(msg: Message) {
		val messageString = msg.data.getString("message")
		Log.d("mytestmessenger", "Receive Service message: $messageString")
	}
}

fun testMessenger() {
	val intent = Intent(this, MyService::class.java)
	val connection = object : ServiceConnection {
		override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
			val serviceMessenger = Messenger(service)
			val message = Message.obtain()
			val data = Bundle()
			data.putString("message", "hello, I am Client!")
			message.data = data
			message.replyTo = mClientMessenger
			serviceMessenger.send(message)
		}

		override fun onServiceDisconnected(name: ComponentName?) {
		}
	}
	bindService(intent, connection, Context.BIND_AUTO_CREATE)
}

Messenger源码分析

Messenger.java代码整体结构

class Messenger implements Parcelable {
    private final IMessenger mTarget;

    /**
     * Create a new Messenger pointing to the given Handler.  Any Message
     * objects sent through this Messenger will appear in the Handler as if
     * {@link Handler#sendMessage(Message) Handler.sendMessage(Message)} had
     * been called directly.
     * 
     * @param target The Handler that will receive sent messages.
     */
    public Messenger(Handler target) {
        mTarget = target.getIMessenger();
    }
	
	/**
     * Create a Messenger from a raw IBinder, which had previously been
     * retrieved with {@link #getBinder}.
     * 
     * @param target The IBinder this Messenger should communicate with.
     */
    public Messenger(IBinder target) {
        mTarget = IMessenger.Stub.asInterface(target);
    }
    
    /**
     * Send a Message to this Messenger's Handler.
     * 
     * @param message The Message to send.  Usually retrieved through
     * {@link Message#obtain() Message.obtain()}.
     * 
     * @throws RemoteException Throws DeadObjectException if the target
     * Handler no longer exists.
     */
    public void send(Message message) throws RemoteException {
        mTarget.send(message);
    }
    /**
     * Retrieve the IBinder that this Messenger is using to communicate with
     * its associated Handler.
     * 
     * @return Returns the IBinder backing this Messenger.
     */
    public IBinder getBinder() {
        return mTarget.asBinder();
    }
	... ... 
}

从Messenger的代码结构上可以看出:

  • 它实现了Parcelable接口,所以在跨进程通信时,可以将Client的Messenger对象作为Message的replyTo参数传递到服务端
  • 构造方法有两个,一个是传入Handler,另一个是传入IBinder,不管是传入哪个,都是为了拿到【IMessenger】接口,那么【IMessenger】接口是什么呢?
  • send(Message message) :发送消息
  • getBinder():将IMessenger接口转为IBinder

IMessenger接口

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

从"mTarget = IMessenger.Stub.asInterface(target);"这段代码就可以看出,【IMessenger】就是一个具有跨进程能力的AIDL接口。
Messenger的基本用法上我们知道,这里的【IBinder】就是连接服务端时返回来的IBinder,再结合下面这段代码:

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

可以知道Client拿到的【IBinder】其实就是服务端的【Messenger】对象通过【Handler.getIMessenger()】方法返回的【IMessenger】接口

Handler.java关键源码:

class 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源码可以看到:

  • 【Handler.getIMessenger()】方法返回的对象是【MessengerImpl 】
  • 【MessengerImpl 】继承自【IMessen.Stub】
  • 【MessengerImpl 】的【send(Message msg)】方法实现就是调用当前【Handler】的【sendMessage】方法

所以我们可以看出,【IMessenger】这个AIDL接口功能最终的实现者就是【Handler】,【Handler】通过对外提供【getIMessenger】方法,将自身包装成具有跨进程能力的【IMessenger】AIDL接口,而【Messenger】只是对【IMessenger】接口再一次包装便于使用而已。

小结

Messenger其实就是Handler支持跨进程调用的增强版,调用Messenger的send方法,本质上就是调用远程的Handler的sendMessage方法。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android 中,可以使用 Handler 进行进程间通信。以下是使用 Handler 进行进程间通信的基本步骤: 1. 在发送方进程中创建 Handler 对象,并在其构造函数中传递一个 Looper 对象。这个 Looper 对象可以通过调用 Looper.myLooper() 或 Looper.getMainLooper() 方法获取。 2. 在接收方进程中创建一个 Messenger 对象,将其作为参数传递给发送方进程的 Handler 对象的构造函数。 3. 在发送方进程中,通过 Messenger.send() 方法向接收方进程发送消息。在发送消息时,需要创建一个 Message 对象,并将其传递给 Messenger.send() 方法。 4. 在接收方进程中,需要创建一个 Handler 对象,并在其 handleMessage() 方法中处理消息。在创建 Handler 对象时,需要将当前线程的 Looper 对象作为参数传递给其构造函数。 5. 在接收方进程中,通过 Messenger 的 bindService() 方法来连接发送方进程的服务,从而接收发送方进程发来的消息。 下面是一个简单的示例代码,用于演示如何在两个进程之间使用 Handler 进行通信: 在发送方进程中: ``` // 创建 Handler 对象 Handler handler = new Handler(Looper.myLooper()) { @Override public void handleMessage(Message msg) { // 处理接收到的消息 } }; // 创建 Messenger 对象 Messenger messenger = new Messenger(handler); // 发送消息 Message message = Message.obtain(); messenger.send(message); ``` 在接收方进程中: ``` // 创建 Handler 对象 Handler handler = new Handler(Looper.myLooper()) { @Override public void handleMessage(Message msg) { // 处理接收到的消息 } }; // 创建 Messenger 对象 Messenger messenger = new Messenger(handler); // 绑定发送方进程的服务 Intent intent = new Intent(); intent.setComponent(new ComponentName("com.example.sender", "com.example.sender.MyService")); bindService(intent, new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { // 连接成功,保存 Messenger 对象 messenger = new Messenger(service); } @Override public void onServiceDisconnected(ComponentName name) { // 连接断开 } }, Context.BIND_AUTO_CREATE); ``` 注意:在进行进程间通信时,需要使用 AIDL 接口来定义消息的格式。具体的实现方式超出了本回答的范围,可以查阅相关文档进行学习。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值