IPC概念
-
使用多进程:
android:process属性 -
Android为每一个进程都分配一个独立的虚拟机,导致在不同的虚拟机中访问同一个类的对象会产生多份副本,即使是
public static int sUerId = 1之类的静态变量也一样 -
使用多进程会造成:
- 静态成员和单例模式完全失效
- 线程同步机制完全失效
SharedPreferences的可靠性下降- Application多次创建
-
Serializable接口
- 要想让一个对象序列化,只需要这个类实现Serializable接口并声明一个serialVersionUID即可
-
Parcelable接口
- 实现
decribleContents方法,writeToParcel方法,和CREATOR
- 实现
-
Binder
Android实现IPC的方式
-
使用Bundle
-
使用文件共享
- 有局限性,比如并发读写
- 文件共享的方式适合在对数据同步要求不高的进程间进行通信,并且要妥善处理并发读写的问题
- 不建议在进程间通信使用SharedPrefetences
-
使用Messenger
- 只能串行的方式处理客户端发来的信息
- 服务端进程
- 我们需要在服务端创建一个Service,同时创建一个Handler并通过它来创建一个Messenger对象,然后在Service的onBind中返回这个Messenger对象底层的Binder即可
- 客户端进程
- 首先绑定服务端的Service,绑定成功后用服务端返回的IBinder对象创建一个Messenger,通过这个Messenger就可以向服务端发送消息了,发送消息类型为Message对象。这就实现了客户端到服务端的通信
- 如果想要服务端回应客户端。需要在客户端创建一个Handler并创建一个新的Messenger,并把这个Messenger对象通过Message的replyTo参数传递给服务端,服务端通过这个replyTo参数就可以回应客户端
-
使用AIDL
- AIDL是日常开发涉及进程间通信时的首选
- 服务端
- 首先创建一个Service,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中,创建一个类继承自AIDL接口中的Stub类并实现Stub中的抽象方法,在Service的onBind方法中返回这个类的对象
- 客户端
- 绑定Service,将服务端返回的Binder对象转成AIDL接口所属的类型,接着就可以调用AIDL中的方法了
- 拓展:
- 使用观察者模式,让服务端为被观察者,客户端为观察者
- 用RemoteCallbackList来实现删除跨进程listener接口
- 服务端进程意外停止,需要重连服务
- 给Binder设置DeathRecipient接听
- 或者在onServiceDisconnected中重连远程服务
- 如何在AIDL中使用权限验证功能
- 可以在onBind中进行验证
- 在服务端的onTransact中进行验证
- 用Binder连接池,将所有AIDL放在同一个Service中去管理
-
使用ContentProvider
-
使用Socket(“套接字”)
- Socket称为“套接字”,分为流式套接字和用户数据报套接字,分别对应于网络传输控制层中的TCP和UDP协议
| 名称 | 优点 | 缺点 | 使用场景 |
|---|---|---|---|
| Bundle | 简单 | 只能传输Bundle支持的数据类型 | 四大组件之间进程通信 |
| 文件共享 | 简单 | 不适合高并发,无法做到进程间即时通信 | 无并发访问情形 |
| AIDL | 一对多并发即时通信 | 一对多通信且有RPC需求 | |
| Messenger | 一对多串行通信,支持实时通信 | 不能处理好高并发,不支持RPC, | 低并发的一对多即时通信,无RPC需求 |
| ContentProvider | 支持一对多并发数据共享, | 理解为受约束的AIDL,主要提供CRUD操作 | 一对多进程间的数据共享 |
| Socket | 功能强大,通过网络传输字节流,支持一对多并发实时通信 | 不支持直接RPC | 网络数据交换 |
参考:《Android开发艺术探索》