Android IPC机制全解析<一>
概要
- 多进程概念及多进程常见注意事项
- IPC基础:Android序列化和Binder
- 跨进程常见的几种通信方式:Bundle通过Intent传递数据,文件共享,ContentProvider,基于Binder的AIDL和Messenger以及Socket。
- Binder连接池
- 各种进程间通信方式的优缺点及适用场景
IPC是 Inter-Process Communication的缩写,意为进程间通信或跨进程通信,是指两个进程之间进行数据交换的过程。
线程是CPU调度的最小单元,同时线程是一种有限的系统资源。进程一般指一个执行单元,在PC和移动设备上指一个程序或者一个应用。一个进程可以包含多个线程,因此进程和线程是包含与被包含的关系。最简单的情况下,一个进程中只可以有一个线程,即主线程,在Android中也叫UI线程。
IPC不是Android中所独有的,任何一个操作系统都需要相应的IPC机制,比如Windows上可以通过剪贴板等来进行进程间通信。Android是一种基于Linux内核的移动操作系统,它的进程间通信方式并不能完全继承自Linux,它有自己的进程间通信方式。
1. Android中的多进程模式
通过给四大组件指定android:processs属性可以开启多进程模式,我们无法给一个线程或一个实体类指定其运行所在的进程。
<activity
android:name=".SecondActivity"
android:process=":remote"/>
<activity
android:name=".ThirdActivity"
android:process="com.example.remote"/>
应用默认的进程是当前包名,以上分别给两个Activity指定了进程,意味着当前应用又增加了两个新进程。假设当前应用包名为com.ipc.example,那么SecondActivity所在的进程为com.ipc.example.remote,“:”的含义是要在当前进程名前面附上当前的包名,而且已“:”开头的进程属于当前应用的私有进程,其他应用的组件不可以和它跑在同一进程。不以“:”开头的进程是全局进程,如指定了ThirdActivity所在的进程为全局进程。
2. 多进程模式的运行机制
新建UserManager类:
public class UserManager {
public static int sUserId = 1;
}
在MainActivity中将sUserId的值修改为2,由于MainActivity在应用默认进程,SecondActivity在指定进程,在SecondActivity中打印sUserId的值会发现sUserId值并没有变,还是1。
出现这样的原因是SecondActivity运行在单独的进程,Android为每个应用分配了一个独立的虚拟机或者说为每个进程都分配了一个独立的虚拟机,不同的虚拟机在内存上都有不同的地址空间,这就导致在不同的虚拟机中访问同一个对象会产生多分副本。上面示例中MainActivity修改了sUserId的值只会影响当前进程,对其他进程不会造成 任何影响。
所有运行在不同进程的四大组件,只要它们之间需要通过内存来共享数据都会失败。一般来说多进程会造成以下几个问题:
- 静态成员和单例模式完全失效
- 线程同步机制完全失效(不在同一进程,,锁的不是同一对象,所以不管锁对象还是锁全局类都无法保证线程同步)
- SharePreferences的可靠性下降
- Application会多次创建(在Application的onCreate()中打印当前进程名证实了同一应用不同进程下,Application会多次创建。这也说明了多进程模式下,不同进程的组件的确会拥有独立的虚拟机、Application以及内存空间)
3. Serializable和Parcelable接口
Serializable和Parcelable可以完成对象的序列化过程,当我们需要通过Intent和Binder传输数据时就需要进行序列化,Serializable是Java提供的一个空接口,为对象提供标准的序列化和反序列化操作。使用简单但是序列化和反序列都会做大量的I/O读写操作,内存开销较大。
Parcelable是Android中的序列化方式,使用稍微复杂,但是效率高。
4. Android中的IPC方式:
4.1: 使用Bundle
四大组件中的其中三个(Activity、Service、Receiver)都是支持在Intent中传递Bundle数据,由于Bundle实现了Parcelable接口,所以它可以方便的在不同进程间传输。
4.2:使用文件共享
文件共享也是一种不错的进程间通信方式,两个进程通过读写同一个文件来交换数据,比如A进程中把数据写入文件,B进程通过读取这个文件来获取数据。但是这种方式也是又一定局限性的,比如并发读写的问题会导致我们读出的数据不是最新的,因此要避免并发读写的发生或者考虑使用线程同步来限制多个线程的读写操作。基于这样的问题,文件共享方式适合对数据同步要求不高的进程之间进行通信。
4.3:使用Messenger
Messenger是一种轻量级的IPC方案,它的底层实现是AIDL,通过Messenger可以在不同进程中传递Message对象,在Message中放入我们需要传递的数据就可以轻松实现数据在进程间传递了。
Messenger的使用很简单,由于它一次处理一个请求,因此在服务端不用考虑线程同步的问题。Messenger实现进程间通信大致可以分为以下几步,分为服务端和客户端。
- 服务端进程
首先需要在服务端新建一个Service来处理客户端发起的请求,同时创建一个Handler并通过它来创建一个Messenger对象,然后在Service的onBind中返回这个Messenger对象底层的Binder即可。 - 客户端进程
客户端进程中首先要绑定服务端的Service,绑定成功后用服务端返回的IBinder对象创建一个Messenger,通过这个Messenger就可以向服务端发送类型为Message的消息了。
注册Service,使其运行在单独的进程,AndroidManifest.xml中配置:
Log日志:
在Messenger中进行数据传递必须将数据放入Message中,而Messenger和Message都实现了Parcelable接口,因此可以跨进程传输。上面的实例只是介绍了如何在服务端接受客户端中发送的请求,但是有时候还需要回应客户端。每当客户端发来一条消息,服务端就自动回复一条“来自服务端的自动回复:消息已收到”。如果需要客服端能够回应客户端,那么和服务端一样,在客户端还需要创建一个新的Messenger,并把这个Messenger对象通过Message的replyTo参数传递给服务端,服务端通过这个replyTo参数就可以回应客户端。
修改后的服务端代码:
修改后的客户端代码:
4.4: 使用AIDL
Messenger是以串行的方式处理客户端的请求,如果有大量的请求同时发送到服务端,服务端仍然只能一个一个处理,此时Messenger就不大合适了,同时Messenger的作用是为了传递消息,且只能传递Bundle支持的数据类型,很多时候需要跨进程调用服务端的方法,这时候可以实用AIDL来实现跨进程的方法调用。AIDL也是Messenger的底层实现,因此Messenger本质上也是AIDL,只不过系统作了封装。实用AIDL进行进程间通信的流程分为服务端和客户端两个方面,下面分别介绍:
- 服务端
服务端首先要创建一个Service用来监听客户端的连接请求,然后创建一个AIDL文件将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中实现这个AIDL接口即可 - 客户端
客户端要做的事情稍微简单些,首先绑定服务端的Service,绑定成功后将服务端返回的Binder对象转成AIDL接口所属的类型,接着就可以调用AIDL中的方法了 - AIDL接口的创建
详情参考:https://www.zhihu.com/question/21581761需要注意的是,如果AIDL文件中用到了自定义的Parcelable对象,那么必须新建一个和它同名的AIDL文件,并在其中声明为Parcelable类型。上面代码中我们用到了BookEntity这个类,所以必须创建BookEntity.aidl,然后将BookEntity定义为Parcelable类型。
服务端的实现
运行在独立进程:
<service
android:name=".service.BookManagerService"
android:process="com.ipc.example.remote"/>
- 客户端实现
这是一次完整的使用AIDL实现进程间通信,但是远远还没有完,AIDL的复杂性远不止这些。下一篇着重总结AIDL的使用。
Android IPC机制全解析<一>的更多相关文章
- Android IPC机制全解析<二>
在AIDL文件中并不是所有的数据类型都可以使用,AIDL支持的数据类型如下: 基本数据类型(int.long.char.boolean.double等) String和CharSequence Lis ...
- Android异步载入全解析之使用多线程
异步载入之使用多线程 初次尝试 异步.异步,事实上说白了就是多任务处理.也就是多线程执行.多线程那就会有各种问题,我们一步步来看.首先.我们创建一个class--ImageLoaderWithoutC ...
- Android异步载入全解析之IntentService
Android异步载入全解析之IntentService 搞什么IntentService 前面我们说了那么多,异步处理都使用钦定的AsyncTask.再不济也使用的Thread,那么这个Intent ...
- Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用
在上一篇文章Android IPC机制(二)用Messenger进行进程间通信中我们介绍了使用Messenger来进行进程间通信的方法.可是我们能发现Messenger是以串行的方式来处理client ...
- Android异步载入全解析之大图处理
Android异步载入全解析之大图处理 异步载入中很重要的一部分就是对图像的处理,这也是我们前面用异步载入图像做示例的原因. 一方面是由于图像处理不好的话会很占内存,并且easyOOM,还有一方面,图 ...
- Android异步载入全解析之使用AsyncTask
Android异步载入全解析之使用AsyncTask 概述 既然前面提到了多线程,就不得不提到线程池,通过线程池,不仅能够对并发线程进行管理.更能够提高他们运行的效率.优化整个App.当然我们能够自己 ...
- 深入理解Android IPC机制之Binder机制
Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe).信号(Sign ...
- android IPC 机制 (开发艺术探索)
一.IPC 机制介绍 IPC是Inter-Process Communication的缩写,含义就是进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程.那么什么是进程,什么是线程,进程和线程 ...
- Handler消息机制与Binder IPC机制完全解析
1.Handler消息机制 序列 文章 0 Android消息机制-Handler(framework篇) 1 Android消息机制-Handler(native篇) 2 Android消息机制-H ...
随机推荐
- configparser配置文件模块
1.configparser的作用 mysql等很多文件的配置如下: [DEFAULT]ServerAliveInterval = 45Compression = yesCompressionLeve ...
- Tcl/tk缩放Truetype字体时的精度问题
最近有国内新客户抱怨我们产品显示的原理图太不专业了,在原理图上使用宋体GB2312设计好中文图表,经过几次缩放时,表格内的文字居然会跑到表格外边,更要命的是打印出来的文档也存在同样的问题. 我研究了一 ...
- 【CNMP系列】CentOS7.0下安装MySql5.6服务
接上一回的话,CentOS7.0下安装好了Nginx服务,对于我们的CNMP,我们可以开始我们的M啦,就是传统意义上的MySql服务 MySql简介 MySQL是一个关系型数据库管理系统,由瑞典MyS ...
- 不恰当的update语句使用主键和索引导致mysql死锁
背景知识: 截至目前,MySQL一共向用户提供了包括DBD.HEAP.ISAM.MERGE.MyIAS.InnoDB以及Gemeni这7种Mysql表类型.其中DBD.InnoDB属于事务安全类表,而 ...
- 图片流量节省大杀器:基于腾讯云CDN的sharpP自适应图片技术实践
目前移动端运营素材大部分依赖图片,基于对图片流量更少,渲染速度更快的诉求,我们推动CDN,X5内核,即通产品部共同推出了一套业务透明,无痛接入的CDN图片优化方案:基于CDN的sharpP自适应图片无 ...
- 关于使用mybatis中mapper instrances,通过session另一种操作方式
String resource = "mybatis-config.xml"; InputStream inputStream = null; try { // 获取SqlSess ...
- 网络安全实验室 脚本关通关writeup
[1]key又又找不到了查看源代码.发现key的路径,点击进行了302跳转,抓包,得到key [2]快速口算要2秒内提交答案,果断上python import requests,re s = requ ...
- MD5加密 32位
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; ...
- background-image 与 img 动画性能对比
开发H5常常会用到滑屏,目前大部分滑屏插件都是通过控制页面的transform属性来实现.尽管如此,我总是发现自己的H5滑动起来就是不如网上一些优秀案例流畅,表现为滑动动画会出现卡顿.跳帧. 后来我发 ...
- http的几种请求的方式(Get、Post、Put、Head、Delete、Options、Trace和Connect)
http的这几种请求方式各有各的特点,适用于各自的环境.下面我就说说这些方式的各自特点: 1.Get:它的原理就是通过发送一个请求来取得服务器上的某一资源.获取到的资源是通过一组HTTP头和呈现数据来 ...