- 简介
- IPC: Inter-Process Communication 进程间通信
- 进程指一个执行单元, 它包含线程, 线程是CPU调度的最小单位
- 不同操作系统上进程间通信的方式
- Linux: 命名管道, 共享内存, 信号量, Socket等
- Android: Binder, Socket等
Android上, 通过使用多进程可以获取多份内存空间, 避开Android对单个应用最大内存的限制
- 多进程模式
- 开启多进程模式
- 在AndroidManifest.xml中为组件指定android:process属性
- 通过JNI在native层fork一个进程
- 使用
:
标识的进程是一种简写, 进程名是包名加上指定的名字, 同时此类进程是当前应用的私有进程, 其他应用的组件不能和它运行在同一个进程, 而普通标识的进程名属于全局进程, 其他应用可以通过指定shareUID的方式与其运行在同一进程中
- 多进程模式的运行机制
- 多进程意味着Android系统会为每个进程分配独立的虚拟机, 导致不同的虚拟机上同一个类的对象会有多个副本, 所以和单进程中的会有区别
- 多进程会导致如下方面的问题
- 静态成员和单例模式失效
- 线程同步机制失效
- SharedPreferences的可靠性降低
- Application会多次创建
- 开启多进程模式
- IPC基础概念
- Serializable接口
- Java提供的序列化接口, 是一个空接口
- serialVersionUID不会对序列化产生影响, 会影响反序列化
- 使用ObjectOutputStream和ObjectInputStream即可完成序列化和反序列化
- serialVersionUID用于标识类, 如果类的serialVersionUID不一样则不能正常的反序列化
- 即使serialVersionUID一样, 如果类名成员变量类型变了, 也会反序列化失败
- 类变量和transient变量不会序列化
- Parcelable接口
- 相比Serializable开销更小
- 使用比Serializable麻烦
- List和Map也可以序列化, 前提是每一个元素都是可序列化的
- 一个使用Parcelable进行进程间通信的例子(IPC->ParcelableIPC)
- Binder
- Serializable接口
- Android中的IPC方式
- Bundle
一个使用Bundle进行进程间通信的例子(IPC->ParcelableIPC) - 使用文件共享
- 有局限性 - 并发读写问题, 只适合对数据同步要求不高的进程间通信
- 不建议在进程间通信时使用SharedPreferences
- 使用Messenger
- 对AIDL做了封装
- 一次处理一个请求, 所以服务端不要考虑线程同步问题
- Message的obj字段在2.2前不支持跨进程传输, 而且它仅支持系统提供的实现了Parcelable的对象, 自定义的Parcelable对象不能传递
- 一个使用Messenger进行进程间通信的例子
- 使用AIDL
一个使用AIDL进行进程间通信的例子(IPC->AIDL) - 使用ContentProvider
一个使用ContentProvider进行进程间通信的例子(IPC->ContentProvider) - 使用Socket
- Bundle
- Binder连接池
- 选用合适的IPC方式
名称 | 有点 | 缺点 | 适用场景 |
---|---|---|---|
Bundle | 简单易用 | 只能传输Bundle支持的数据类型 | 四大组件间的进程间通信 |
文件共享 | 简单易用 | 不适合高并发场景, 无法做到即时通信 | 无并发访问情形, 交换简单的数据实时性不高的场景 |
AIDL | 功能强大, 支持一对多并发通信, 支持实时通信 | 使用复杂, 需处理线程同步 | 一对多通信, 且有RPC需求 |
Messenger | 功能一般, 支持一对多串行通信, 支持实时通信 | 不能处理高并发情形, 不支持RPC, 数据通过Message传输, 只能传输Bundle支持的数据类型 | 低并发的一对多即时通信, 或者无需返回结果的RPC请求 |
ContentProvider | 在数据源访问方面功能强大, 支持一对多并发数据共享, 可通过Call方法扩展其操作 | 可理解为受约束的AIDL, 主要提供数据源的CRUD操作 | 一对多的进程间数据共享 |
Socket | 功能强大, 可以通过网络传输字节流, 支持一对多并发实时通信 | 实现细节烦琐, 不支持直接的RPC | 网络数据交换 |