随笔Android IPC进程通信之——Messenger

2024-06-08 13:32

本文主要是介绍随笔Android IPC进程通信之——Messenger,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

随笔Android IPC进程通信之——Messenger

android中用于进程通信和数据共享的方式有多种,最基本的Bundle,文件共享,Messenger,AIDL,ContentProvider,Socket等,他们的区别和使用场景这里就不再说了,详情自行查看了解了解,本文直接介绍方式之一Messenger(信使)的使用方式。

代码为例,开始看看我们遇到的问题,模拟多进程数据同步问题

1.新建一个IPCDemo,创建一个自己的Applciation并声明一个公用变量value

这里写图片描述

2.新建两个Activity,在第一个MainActivity中修改Oncreate中修改 Application中value值为8
这里写图片描述

由MainActivity进入第二个页面(服务Activity)注意此activity在Manifest中配置中添加android:process=”:remote”,目的是让其单独运行在一个进程中,和MainActivity不同进程。
这里写图片描述

在ServerActivity中我们同样打印Applcation中的value;
结果如下:
这里写图片描述

3.引起的问题 我们知道一个应用中Application是一个重量级的,由系统创建的单一实例,其中的数据是共享的,那么这里我们在MainActivity中修改了value值,这个应用中的其他访问的地方应该都是修改后的值,但上面的结果却不是这样。

原因就在于,我们的ServerActivity配置了android:process=":remote",这会导致ServerActivity运行在另一进程中,说白了就是,MainActivity是一个应用,ServerActivity是一个应用,既然是两个不同应用,那么就会有两个不同的Application实例,Application会创建多次(这里两次),这两个实例分别位于不同进程(应用中),这就是为什么修改第一个全局值,而第二个进程中的值没有任何影响的原因。

4.解决问题 我们如何让第一个进程修改变量值的时候,通知另一个进程同步修改对应的值?接下来就利用本文介绍的Messenger。

Messenger 运用

messenger 其实是基于消息的进程通信方式,最基本的理解就是有客户端,服务端如下图:
这里写图片描述

接下来代码介绍:
我们的MainActivity用来充当客户端,ServerActivity充当服务端,因为两个页面完全运行在不同的进程中。

首先,创建一个MessengerService,并在manifest中配置成和ServerActivity中相同的进程。代码如下:

/*** Created by Frosty on 2017/6/13.*//public class    MessengerService extends Service{public static String TAG = MessengerService.class.getSimpleName();public final static int FROM_CLIENT = 1;//来此客户端请求public final static int FROM_SERVICE= 2;//来此服务端请求private Messenger msngerCurrent;//当前类使用(发送消息、接收处理消息)@Overridepublic void onCreate() {super.onCreate();msngerCurrent = new Messenger(new MessengerHandler());}@Nullable@Overridepublic IBinder onBind(Intent intent) {return msngerCurrent.getBinder();}public static class MessengerHandler extends Handler{@Overridepublic void handleMessage(Message msg) {switch (msg.what){case FROM_CLIENT:///1.处理接受消息Log.e(TAG,"收到来自客户端【"+msg.getData().getString("name")+"】的消息:"+msg.getData().getString("content"));MyApplication.value = msg.getData().getInt("value");//2.拿到客户端发送消息附带的Messenger,用它回传消息Messenger msngerReply = msg.replyTo;//封装回传消息Message replyMsg = Message.obtain(null,FROM_SERVICE);Bundle bundle = new Bundle();bundle.putString("name","阿里云");bundle.putString("content","你好,我这边已经同步修改,值为:"+MyApplication.value);replyMsg.setData(bundle);try {msngerReply.send(replyMsg);//回传消息}catch (Exception e){}break;default:break;}}}
}
这里暂时只说明这个服务的功能,利用MessengerHandler处理发送自客户端来的数据,通过msg.what匹配。

所以我们在客户端(MainActivity中去注册绑定这个服务,并在修改appvalue时候发送一个消息给这个服务)

public class MainActivity extends AppCompatActivity {private Messenger msngerCurrent;private class MessengerHandler extends Handler{@Overridepublic void handleMessage(Message msg) {switch (msg.what){case MessengerService.FROM_SERVICE:Log.e("MessengerService","收到来自服务端【"+msg.getData().getString("name")+"】的回应:"+msg.getData().getString("content"));unbindService(serviceConnection);break;}}}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MyApplication.value = 8;//此处修改值Log.e("appvalue","MainActivity中获取到的value:"+MyApplication.value);/*绑定服务*/bindRemoteService();msngerCurrent = new Messenger(new MessengerHandler());findViewById(R.id.btn_requestServer).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(MainActivity.this,ServerActivity.class);startActivity(intent);}});}///服务链接状态监听private ServiceConnection serviceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Messenger messengerClient = new Messenger(service);/*封装消息体*/Message msg = Message.obtain(null,MessengerService.FROM_CLIENT);//对应服务端接受码Bundle bundle = new Bundle();bundle.putString("name","张山");bundle.putString("content","我修改了我们的共享值,请你务必修改!");bundle.putInt("value",MyApplication.value);msg.setData(bundle);msg.replyTo=msngerCurrent;//发送try{messengerClient.send(msg);}catch (Exception e){}}@Overridepublic void onServiceDisconnected(ComponentName name) {}};public void bindRemoteService(){Intent intent = new Intent(this, MessengerService.class);bindService(intent,serviceConnection, Context.BIND_AUTO_CREATE);}@Overrideprotected void onDestroy() {unbindService(serviceConnection);super.onDestroy();}
}

我们详细解释一下工作流程
- 我们首先得创建一个ServiceConnection 用于检测服务绑定后或者断开后的操作如下图,绑定服务链接后,回掉调nServiceConnected方法,在这个方法中,我们构造一个客户端Messenger
这里写图片描述并用message封装数据,然后用这个Messenger发送消息即可

发送消息后,MessengerService便可以接收到消息处理,修改当前进程的appvalue值,并回传附加消息给客户端,注意这里回传的Messenger,直接在获取消息体中用msg.replyTo获取,前提是客户端相应的在传过来的msg中replyTo赋值Mesenger,此messenger在客户端也用来处理服务端响应回来的数据。

这里写图片描述

5.结果 我们重启应用,重新打印两个值
这里写图片描述
发现在主进程修改appvalue后,另一个进程获取到的值也及时得到同步了。

End注意:Messenger通信,可使用它进行进程间的通信,而Messenger对Service的请求采用队列的方式,因此它不支持多线程通信。

这篇关于随笔Android IPC进程通信之——Messenger的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1042322

相关文章

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

[Linux]:进程(下)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:Linux学习 贝蒂的主页:Betty’s blog 1. 进程终止 1.1 进程退出的场景 进程退出只有以下三种情况: 代码运行完毕,结果正确。代码运行完毕,结果不正确。代码异常终止(进程崩溃)。 1.2 进程退出码 在编程中,我们通常认为main函数是代码的入口,但实际上它只是用户级

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

android应用中res目录说明

Android应用的res目录是一个特殊的项目,该项目里存放了Android应用所用的全部资源,包括图片、字符串、颜色、尺寸、样式等,类似于web开发中的public目录,js、css、image、style。。。。 Android按照约定,将不同的资源放在不同的文件夹中,这样可以方便的让AAPT(即Android Asset Packaging Tool , 在SDK的build-tools目

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使