1、IPC的说明android
IPC是Inter-Process Communication的缩写,含义为进程间通讯或跨进程通讯,是指两个进程之间进行数据交换的过程。git
IPC不是Android独有的,任何一个操做系统都须要有相应的IPC机制,好比Windows上能够经过剪贴板,管道和邮槽来进行进程间通讯;Linux上能够经过命名管道、共享内容、信号量等进行进程间通讯。github
对于Android来讲,它是一种基于Linux内核的移动操做系统,但它的进程间通讯方式并不能彻底继承自Linux;相反,它有本身的进程间通讯方式。数据库
在Android中能够经过Binder轻松的实现进程间通讯。Android还支持Socket,经过Socket能够实现任意两个终端之间的通讯,同一设备的两个进程经过Socket通讯天然也是能够的。编程
2、Android中IPC的使用缓存
首先,只有面对多进程的状况才须要考虑进程间通讯。多进程的状况分为两种:服务器
第一种是一个应用由于某些缘由,自身须要采用多进程模式来实现,好比有些模块须要运行在单独的进程中、或者为了加大一个应用的可以使用内存,须要经过多进程来获取多份内存空间。网络
另外一种是当前应用须要向其余的应用获取数据,因此必须采用跨进程的方式来获取数据,好比使用系统的ContentProvider去查询数据。并发
经过给四大组件在AndroidMenifest中指定android:process属性,能够轻易地开启多进程模式。框架
3、Android中IPC带来的问题
两个应用共享数据:Android系统会为每一个应用分配一个惟一的UID,具备相同UID的应用才能共享数据。两个应用经过ShareUID跑在同一个进程是有要求的,须要这两个应用有相同的ShareUID而且签名相同才能够。在这种状况下,他们能够相互访问对方的私有数据,好比data目录,组件信息等,无论他们是否跑在同一个进程。
Android系统为每一个应用分配了一个独立的虚拟机,或者说为每个进程都分配一个独立的虚拟机,不一样的虚拟机在内存分配上有不一样的地址空间,这就致使在不一样的虚拟机中访问同一个对象会产生多分副本。全部运行在不一样进程中的四大组件,只要它们之间须要经过内存来共享数据,都会共享失败,这也是多进程带来的主要影响。
通常来讲,使用多进程会形成以下的问题:
(1)静态成员和单例模式彻底失效(不一样的虚拟机中访问同一个对象会产生多分副本)
(2)线程同步机制彻底失效(不在同一块内存,无论是所对象仍是锁全局类都没法保证线程同步)
(3)SharePreferences的可靠性降低(不支持两个进程同时写操做)
(4)Application会屡次建立(由于建立新进程会分配独立虚拟机,至关于启动一个新的应用)
虽然说不能直接的共享内存,可是经过跨进程通讯仍是能够实现数据交互。
4、Android中各类IPC方式
一、使用Bundle
四大组件中三大组件Activity、Service、Receiver都支持在Intent中传递Bundle数据。
因为Bundle实现了Parcelable接口,因此它能够很方便的在不一样的进程间传输数据。固然咱们传输的数据必须可以被序列化,好比基本类型、实现了Parcelable接口的对象、实现了Serializable接口的对象以及一些Android支持的特殊对象。
二、使用文件共享
两个进程经过读写同一个文件来交换数据,好比A进程把数据写入文件,B进程经过读取这个文件来获取数据。
Android系统基于Linux,使得并发读写文件能够没有限制的进行,甚至两个线程同时对文件读写操做都是容许的,尽管可能出问题,所以文件共享方式适合在对数据同步要求不高的进程间进行通讯。
SharedPreferences也属于文件的一种,可是因为系统对它的读写有必定的缓存策略,即在内存中会有一份SharedPreferences文件的缓存;所以在多进程模式下,系统对它的读写就变得不可靠,会有很大概率丢失数据,不建议在进程间通讯中使用SharedPreferences。
三、使用Messenger
Messenger能够理解为信使,经过它能够再不一样进程中传递Message对象,在Message中放入咱们须要传递的数据,就能够实现数据的进程间传递了。
Messenger是一种轻量级的IPC方案,它的底层实现是AIDL。因为它一次处理一个请求,所以在服务端不须要考虑线程同步的问题,由于服务端不存在并发执行的情形。
四、使用AIDL
AIDL是 Android Interface definition language的缩写,它是一种android内部进程通讯接口的描述语言。AIDL能够处理发送到服务器端大量的并发请求(不一样与Messenger的串行处理方式),也能够实现跨进程的方法调用。
在Android中使用方法:建立一个Service和一个AIDL接口,接着建立一个类继承自AIDL接口中的Stub类并实现Stub中的抽象方法,在Service的onBind方法中返回这个类的对象,而后客户端绑定服务端Service,创建链接后就能够访问远程服务器了。
五、使用ContentProvider
ContentProvider是Android中提供的专门用于不一样应用间进行数据共享的方式,天生适合进程间通讯。
ContentProvider的底层实现也是Binder,可是它的使用过程比AIDL简单的多,由于系统作了封装,使得无需关心细节便可轻松实现IPC。ContentProvider主要以表格的形式组织数据,和数据库很相似,但ContentProvider对底层的数据存储方式没有任何要求,既可使用Sqlite数据库,也可使用文件方式,甚至可使用内存中的一个对象来存储。
六、使用Socket
Socket套接字,是网络通讯中的概念,分为流式套接字和用户数据奥套接字两种,对应于网络的传输控制层中的TCP和UDP协议。
两个进程能够经过Socket来实现信息的传输,Socket自己能够支持传输任意字节流。
===选择合适的IPC方式===,以下表
名称 | 优势 | 缺点 | 适用场景 |
Bundle | 简单易用 | 只能传输Bundle支持的数据类型 | 四大组件的进程间通讯 |
文件共享 | 简单易用 | 不适合高并发场景,而且没法作到进程间 即时通讯 |
无并发访问清醒,交换简单的数据,实时性不搞的场景 |
AIDL | 功能强大,支持一对多并发通讯,支持实时通讯 | 使用稍复杂,须要处理好线程同步 | 一对多通讯且有RPC需求 |
Messenger | 功能通常,支持一对多串行通讯,支持实时通讯 | 不能很好的处理高并发情形,不支持RPC,数据经过Message进行传输,所以只能传输Bundle支持的数据类型 | 低并发的一对多即时通讯,无RPC需求 |
ContentProvider | 在数据源访问方面功能强大,支持一对多并发数据共享, 可经过Call方法扩展其余操做 |
能够理解为受约束的AICL,主要提供数据的CRUD数据 | 一对多的进程间数据共享 |
Socket | 功能强大,能够经过网络传输字节流,支持一对多并发实时通讯 | 实现细节稍微繁琐,不支持直接的RPC | 网络数据交换 |
RPC(Remote Procedure Call,远程过程调用)是种C/S的编程模式,出于一种类比的愿望,在一台机器上运行的主程序,能够调用另外一台机器上准备好的子程序。
经过RPC能够充分利用非共享内存的多处理器环境,能够简便地将你的应用分布在多台工做站上,应用程序就像运行在一个多处理器的计算机上同样。
5、Binder介绍
Binder是Android系统进程间通讯方式之一。Linux已经拥有的进程间通讯IPC手段包括: 管道(Pipe)、信号(Signal)、跟踪(Trace)、插口(Socket)、报文队列(Message)、共享内存(Share Memory)和信号量(Semaphore)。
Binder框架定义了四个角色:Server,Client,ServiceManager以及Binder驱动。
其中Server,Client,ServiceManager运行于用户空间,驱动运行于内核空间。Binder就是一种把这四个组件粘合在一块儿的粘结剂了,其中,核心组件即是Binder驱动程序了,Service Manager提供了辅助管理的功能,Client和Server正是在Binder驱动和Service Manager提供的基础设施上,进行Client-Server之间的通讯。这四个角色的关系和互联网相似:Server是服务器,Client是客户终端,ServiceManager是域名服务器(DNS),驱动是路由器。
Binder的理解:
一、从IPC角度来讲,Binder是Android中的一种跨进程通讯方式,该方式在Linux中没有;
二、从Android Framework角度来讲,Binder是ServiceManager链接各类Manager和相应ManagerService的桥梁;
三、从Android应用层来讲,Binder是客户端和服务端进行通许in的媒介,当BindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,经过这个Bind而对象,客户端就能够获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务。
在Android开发中,Binder主要用在Service中,包括AIDL和Messenger,普通服务中的Binder不涉及进程间通讯。
直观来说,Binder是Android中的一个类,实现了IBinder接口。
Binder的工做机制:
当客户端发起远程请求时,因为当前线程会被挂起直至服务端进程返回数据,因此一个远程方法是很耗时的,那么不能在UI线程中发起此远程请求;
因为服务端的Binder方法运行在Binder的线程池中,因此Binder方法无论是否耗时都应该采用同步的方式去实现,由于它已经运行在一个线程中了。
6、具体实例