Binder的IPC方式
[TOC]
1. Bundle
四大组件中三大组件(Activity、Service、Receiver)都支持Intent传递Bundle数据,Bundle实现了Parcelable接口,所以可以在不同进程间传输,具体传递的数据类型,可以根据Bundle所支持的类型。
2. 文件共享
两个进程通过读/写同一个文件来进行交换数据。
- 通过 ObjectOutputStream / ObjectInputStream 序列化一个对象到文件中,或者在另一个进程从文件中反序列这个对象。注意:反序列化得到的对象只是内容上和序列化之前的对象一样,本质是两个对象。
- 文件并发读写会导致读出的对象可能不是最新的,并发写的话那就更严重了 。所以文件共享方式适合对数据同步要求不高的进程之间进行通信,并且要妥善处理并发读写问题。
- SharedPreferences 底层实现采用XML文件来存储键值对。系统对它的读/写有一定的缓存策略,即在内存中会有一份 SharedPreferences 文件的缓存,因此在多进程模式下,系统对它的读/写变得不可靠,面对高并发读/写时 SharedPreferences 有很大几率丢失数据,因此不建议在IPC中使用 SharedPreferences 。
3. Messenger
Messenger是一种轻量级的IPC方案,他的底层实现是AIDL,这个可以通过他的构造方法看到:mTarget = IMessenger.Stub.asInterface(target);
1. 服务端进程
创建Service,同时创建Handler并通过它创建Messenger,在service的onBind中返回Messenger底层的Binder。
1 | public class MessengerService extends Service { |
2. 客户端进程
绑定服务端的Service,绑定成功后用服务端返回的IBinder创建Messenger,通过这个Messenger的send方法就可以给服务端发送消息了,发送消息的类型为Message对象。
1 | private Messenger serviceMessenger; |
案例
如果需要服务端可以回应客户端,也需要在客户端创建一个Handler并创建Messenger,并通过Message的replyTo参数传递给服务端。
具体案例参考:MessengerDemo
工作原理
4. AIDL
Messenger不适合应用于有大量并发请求的情况,Messenger的主要的作用是为了传递消息,另外,如果我们需要跨进程调用服务端的方法,那Messenger就无法做到了,可以通过AIDL实现。
参考:Binder:AIDL
5. ContentProvider
ContentProvider是Android提供的专门用于不同进程间数据共享的方式,和Messenger一样底层实现是Binder。
系统预置了许多ContentProvider,比如通信录、日程表信息等,只需要通过ContentResolver的query、update、insert和delete方法即可。
创建自定义的ContentProvider,只需继承ContentProvider类并实现 onCreate 、 query 、 update 、 insert 、 getType 六个抽象方法即可。getType用来返回一个Uri请求所对应的MIME类型,剩下四个方法对应于CRUD操作。这六个方法都运行在ContentProvider进程中,除了 onCreate 由系统回调并运行在主线程里,其他五个方法都由外界调用并运行在Binder线程池中。
ContentProvider是通过Uri来区分外界要访问的数据集合,例如外界访问ContentProvider中的表,我们需要为它们定义单独的Uri和Uri_Code。根据Uri_Code,我们就知道要访问哪个表了。
query、update、insert、delete四大方法存在多线程并发访问,因此方法内部要做好线程同步。 若采用SQLite并且只有一个SQLiteDatabase,SQLiteDatabase内部已经做了同步处理。若是多个SQLiteDatabase或是采用List作为底层数据集,就必须做线程同步。
参考Demo:案例Demo
6. Socket
Socket 又称为“套接字”,分为流式套接字和用户数据报套接字,分别对应网络传输层的TCP和UDP协议。
参考Demo:SocketDemo
IPC方式的优缺点及使用场景
名称 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
Bundle | 简单易用 | 只能传递Bundle支持的数据类型 | 四大组件间的进程间通讯 |
文件共享 | 简单易用 | 不适合高并发,并且无法做到进程间的即时通讯 | 无并发访问场景,交换简单数据且实时性不高的场景 |
AIDL | 功能强大,支持一对多并发通讯且实时通讯 | 使用复杂,需要处理好线程同步 | 一对多通讯且RPC需求 |
Messenger | 功能一般,支持一对多的串行通讯,支持实时通讯 | 不能很好的处理高并发,不支持RPC,数据通过Message传输,因此只能传递Bundle支持的类型数据 | 低并发的即时通讯,无需支持RPC或者不需要返回结果的RPC需求 |
ContentProvider | 数据源访问方面功能强大,支持一对多的高并发数据共享,可以通过Call扩展其他功能 | 可以理解为受约束的AIDL,主要提供数据源的CRUD操作 | 一对多的进程间数据共享 |
Socket | 功能强大,可以通过网络传输字节流,支持一对多的并发通讯 | 实现细节繁琐,不支持直接的RPC | 网路数据交换 |