1.概述

项目中常用到的进程间通信更多是用AIDL,在前阵子复习的时候才了解还有 Messenger 这种方法。既然要学习就记录下,以后要用的时候才能快速的掌握。

Messenger 是一种轻量级的IPC方案,它的底层实现是AIDL,可以在不同进程中传递 Message 对象,它一次只处理一个请求,在服务端不需要考虑线程同步的问题,服务端不存在并发执行的情况。

2. Messenger的构造方法

Public constructors

Messenger(Handler target)

Create a new Messenger pointing to the given Handler.

Messenger(IBinder target)

Create a Messenger from a raw IBinder, which had previously been retrieved with getBinder().

3. Messenger 使用

3.1 客户端步骤:

3.1.1 创建一个handler对象,并实现 handleMessage() 方法,用户接收客户端的消息。

3.1.2 创建Messenger ,封装handler。

3.1.3 用Messenger的 getBinder() 方法获取一个IBinder对象,通过 onBind 返回给客户端。

服务端的Service:

package cn.zzw.messenger.server;import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;public class MessengerService extends Service {private static final String TAG = "MessengerService";private MessengerHandler mHandler = new MessengerHandler();private Messenger mMessenger = new Messenger(mHandler);private static final int MSG_SUM = 10086;private class MessengerHandler extends Handler {@Overridepublic void handleMessage(Message msg) {if(msg.what==MSG_SUM){Log.e(TAG,"handleMessage");try {int arg1 = msg.arg1;int arg2=msg.arg2;Message msgToClient=Message.obtain(msg);msgToClient.arg1=arg1+arg2;msg.replyTo.send(msgToClient);} catch (RemoteException e) {}}}}@Overridepublic IBinder onBind(Intent intent) {return mMessenger.getBinder();}@Overridepublic void onDestroy() {super.onDestroy();mHandler.removeCallbacksAndMessages(null);}
}

3.2 客户端步骤:

3.2.1 在 Activity 中绑定服务。

3.2.2 创建ServiceConnection并在其中使用 IBinder 将 Messenger实例化

3.2.3 使用Messenger向服务端发送消息

客户端主要代码:

package cn.zzw.messenger.client;import androidx.appcompat.app.AppCompatActivity;import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;public class MainActivity extends AppCompatActivity {private static final String TAG = "MessengerClient";private TextView mTv;private Messenger mService;private static final int MSG_SUM = 10086;private MessengerHandler mHandler = new MessengerHandler();private Messenger mMessenger = new Messenger(mHandler);private class MessengerHandler extends Handler {@Overridepublic void handleMessage(Message msg) {if(msg.what==MSG_SUM){Log.e(TAG,"handleMessage");int arg1 = msg.arg1;Log.e(TAG,"handleMessage:"+arg1);Toast.makeText(MainActivity.this,"The Result is "+arg1,Toast.LENGTH_SHORT).show();}}}private ServiceConnection conn=new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {//获取服务端关联的Messenger对象mService = new Messenger(iBinder);Log.e(TAG,"onServiceConnected");}@Overridepublic void onServiceDisconnected(ComponentName componentName) {Log.e(TAG,"onServiceDisconnected");mService=null;}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bindToServserService();mTv = findViewById(R.id.mTv);findViewById(R.id.mBtn_cal).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Message msg = Message.obtain(null, MSG_SUM, 10, 500);msg.replyTo = mMessenger;if(null!=mService){//往服务端发送消息try {Log.e(TAG,"mService.send");mService.send(msg);} catch (RemoteException e) {e.printStackTrace();}}}});}/** 绑定服务端的Service*/private void bindToServserService() {Intent intent=new Intent();intent.setPackage("cn.zzw.messenger.server");intent.setAction("CN.ZZW.MESSENGER.SERVER");bindService(intent,conn,BIND_AUTO_CREATE);}@Overrideprotected void onDestroy() {super.onDestroy();unbindService(conn);mHandler.removeCallbacksAndMessages(null);}
}

4. 运行结果

client端的log:

E/MessengerClient: mService.send
E/MessengerClient: mService.sendhandleMessagehandleMessage:510
E/MessengerClient: handleMessagehandleMessage:510

Server端的log:

E/MessengerService: handleMessage
E/MessengerService: handleMessage
E/MessengerService: handleMessage
E/MessengerService: handleMessage
E/MessengerService: handleMessage

5.原理

先看下 Messenger 的源码,代码行数非常少:

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/os/Messenger.java

/** Copyright (C) 2006 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package android.os;/*** Reference to a Handler, which others can use to send messages to it.* This allows for the implementation of message-based communication across* processes, by creating a Messenger pointing to a Handler in one process,* and handing that Messenger to another process.** <p>Note: the implementation underneath is just a simple wrapper around* a {@link Binder} that is used to perform the communication.  This means* semantically you should treat it as such: this class does not impact process* lifecycle management (you must be using some higher-level component to tell* the system that your process needs to continue running), the connection will* break if your process goes away for any reason, etc.</p>*/
public final 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();}/*** 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();}/*** Comparison operator on two Messenger objects, such that true* is returned then they both point to the same Handler.*/public boolean equals(Object otherObj) {if (otherObj == null) {return false;}try {return mTarget.asBinder().equals(((Messenger)otherObj).mTarget.asBinder());} catch (ClassCastException e) {}return false;}public int hashCode() {return mTarget.asBinder().hashCode();}public int describeContents() {return 0;}public void writeToParcel(Parcel out, int flags) {out.writeStrongBinder(mTarget.asBinder());}public static final Parcelable.Creator<Messenger> CREATOR= new Parcelable.Creator<Messenger>() {public Messenger createFromParcel(Parcel in) {IBinder target = in.readStrongBinder();return target != null ? new Messenger(target) : null;}public Messenger[] newArray(int size) {return new Messenger[size];}};/*** Convenience function for writing either a Messenger or null pointer to* a Parcel.  You must use this with {@link #readMessengerOrNullFromParcel}* for later reading it.* * @param messenger The Messenger to write, or null.* @param out Where to write the Messenger.*/public static void writeMessengerOrNullToParcel(Messenger messenger,Parcel out) {out.writeStrongBinder(messenger != null ? messenger.mTarget.asBinder(): null);}/*** Convenience function for reading either a Messenger or null pointer from* a Parcel.  You must have previously written the Messenger with* {@link #writeMessengerOrNullToParcel}.* * @param in The Parcel containing the written Messenger.* * @return Returns the Messenger read from the Parcel, or null if null had* been written.*/public static Messenger readMessengerOrNullFromParcel(Parcel in) {IBinder b = in.readStrongBinder();return b != null ? new Messenger(b) : null;}/*** 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);}
}

这时候我们在回头看两个构造方法:

 1. public Messenger(Handler target) {mTarget = target.getIMessenger();}2. public Messenger(IBinder target) {mTarget = IMessenger.Stub.asInterface(target);}

两个构造方法内部都是初始化对象 mTarget:

private final IMessenger mTarget;

再看看 IMessenger,是一个AIDL文件:

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/os/IMessenger.aidl

/* //device/java/android/android/app/IActivityPendingResult.aidl
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/package android.os;import android.os.Message;/** @hide */
oneway interface IMessenger {void send(in Message msg);
}

在看看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);}}

从以上代码,可以看出Messenger又跟Binder联系起来了。 最终还是AIDL文件来完成的,只不过Messenger进行了深度的封装AIDL,使用起来更简单。

最后,附上文中的示例代码:https://download.csdn.net/download/zzw0221/11260381

参考:

https://blog.csdn.net/hzw2017/article/details/81090319

https://www.jianshu.com/p/48e212d1fde4

Android 进程间通信:Messenger相关推荐

  1. Android进程间通信 Messenger详解

    1. 概念 Messenger,即进程间通信的信使.它是基于Message的进程间通信,我们可以像在线程间利用Handler.send(Message)一样. Messenger是一种轻量级的IPC方 ...

  2. Android进程间通信 - 几种方式的对比总结

    文章目录 什么是RPC 什么是IPC 参考 什么是RPC RPC(Remote Procedure Call)即远程过程调用,它是一种通过网络从远程计算机程序上请求服务,在不需要了解底层网络技术的协议 ...

  3. Android 基于Message的进程间通信 Messenger完全解析

    转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/47017485: 本文出自:[张鸿洋的博客] 一.概述 说到Android进程间 ...

  4. Android 进程间通信——AIDL

    代码地址如下: http://www.demodashi.com/demo/12321.html 原文地址:http://blog.csdn.net/vnanyesheshou/article/det ...

  5. 浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路(1)

    上一篇文章Android进程间通信(IPC)机制Binder简要介绍和学习计划简要介绍了Android系统进程间通信机制Binder的总体架构,它由Client.Server.Service Mana ...

  6. 浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路

    原文地址: http://blog.csdn.net/luoshengyang/article/details/6621566 上一篇文章Android进程间通信(IPC)机制Binder简要介绍和学 ...

  7. Android进程间通信(IPC)机制Binder简要介绍和学习计划

    在Android系统中,每一个应用程序都是由一些Activity和Service组成的,这些Activity和Service有可能运行在同一个进程中,也有可能运行在不同的进程中.那么,不在同一个进程的 ...

  8. Android中Messenger的使用

    2019独角兽企业重金招聘Python工程师标准>>> 我们使用Handler都是在一个进程中使用的,如何跨进程使用Handler? 其实这个问题不难解决,自己动手对binder进行 ...

  9. Android 进程间通信之管道 - pipe

    文章目录 Android 进程间通信专栏 linux支持的进程间通信 管道 - pipe 概要 配置环境 android 系统中使用管道的场景 Android 进程间通信专栏 linux支持的进程间通 ...

最新文章

  1. 分享基于EF6、Unitwork、Autofac的Repository模式设计
  2. Python 计算Mesh顶点法向量
  3. 运维:windows+python+route的一次相遇
  4. win10 cortana 搜索无效怎么解决
  5. quartz java 线程 不释放_java Quartz 内存泄漏
  6. android显示网络图片控件,Android控件之ImageView(二)
  7. 苹果一半员工未接受4年制大学教育 库克却对此感到骄傲
  8. Canvas绘图基础(一)
  9. idea新建一个java项目_创建第一个Java项目(Create First Java Project)
  10. 计算机安全模式启动时蓝屏,电脑如何进入安全模式修复蓝屏故障
  11. NFine.Framework框架去除cookie后门
  12. POJ - 2718 Smallest Difference
  13. 电脑Windows磁盘修复工具如何使用
  14. Android相对布局简单案例(附完整源码)
  15. 考研政治|马克思主义基本原理
  16. 定点 浮点 神经网络 量化_定点量化
  17. 硬盘开盘数据恢复成功,笔记本硬盘开机无法识别到硬盘
  18. JMeter5.0的脚本录制
  19. 如何分析多个宅急送物流详情,并筛选代收单号
  20. 面试必备:高频算法题汇总「图文解析 + 教学视频 + 范例代码」必问之 排序 + 二叉树 部分!

热门文章

  1. STM32单片机智能全自动多功能洗碗机加热放水烘干紫外消毒
  2. 阿里发布免费的全新可变字体;Stability AI CEO:5年内,人类程序员将不复存在;Perl 5.38发布|极客头条
  3. 【Qt开发】QTime类
  4. Python 拼图成心【大小,图数可调节】
  5. 移动硬盘使用exfat方法
  6. 中山大学计算机专硕 学硕,2014年中山大学计算机学硕考研经验
  7. mt4交易平台哪个好?不妨试试福瑞斯外汇平台
  8. 系统错误 无法启动此程序,因为计算机中丢失MSVCP140_1.dll。尝试重新安装该程序已解决此问题
  9. 苹果电脑删除下载的更新文件_iOS14首发上手体验以及iOS14描述文件下载更新教程...
  10. 【Shader】扭曲能量罩特效