# 读 Android 开发艺术探索 &4
来源:互联网 发布:floyd算法结果怎么看 编辑:程序博客网 时间:2024/06/04 19:57
关键词:IPC 方式 / 共享文件 / ContentProvider / Messenger / Intent + extras / Socket / Bundle
本次笔记梳理了所有可以进行跨进程通信的常见方式,包括使用 Bundle、使用文件共享、使用 Messenger、使用 AIDL、使用 ContentProvider、使用 Socket。
1. 使用 Bundle #
- 是一种最简单的进程间通信;
- 用来直接传递数据,在 Bundle 中附加我们需要传输给远程进程的信息并通过 Intent 发送出去,我们传输的数据也应该被序列化;
- 四大组件中的 Activity / Service / Receiver 都支持在 Intent 中传递 Bundle 数据;
- Bundle 实现了 Parcelable 接口,可以方便地在不同进程间传输;
- A 进程在进行一个计算,计算完成之后要启动 B 进程中的一个组件并把计算结果传递给 B 进程,但是这个计算结果不支持写入 Bundle 中,无法通过 Intent 来传输怎么办?
最简单方案:将需要在 A 中计算的任务转移到 B 进程的后台 Service 中去执行,这样不断避免了进程间通信的问题,还只用了很小的代价。
2. 使用文件共享 #
- 两个进程通过读 / 写同一个文件来交换数据,A 把数据写入文件,B 通过读取这个文件来获取数据;
- Android 系统基于 Linux,使得其并发读 / 写文件可以没有限制的进行,甚至两个线程同时对同一个文件进行写操作都可以,尽管会出现问题;
- 可以序列化一个对象到文件系统中的同时从另一个进程中恢复这个对象;
- 文件共享方式适合在对数据同步要求不高的进程之间进行通信,并且妥善处理并发读写的问题;
- 不建议在进程间通信中使用 SharedPreferences,SharedPreferences 是 Android 中提供的轻量级存储方案,通过键值对的方式来存储数据,在底层上采用 XML 文件来存储键值对,目录位于 /data/data/package_name/shared_prefs 目录下,属于文件的一种,在多线程模式下,面对高并发的读 / 写访问会丢失数据,因为有缓存策略,读写变得不可靠;
3. 使用 Messenger #
- 是一种轻量级的 IPC 方案,底层实现是 AIDL;
- 可以在不同的进程中传递 Message 对象,信使;
- 对 AIDL 进行了封装
- 一次只处理一个请求,在服务端不用考虑线程同步的问题,服务端不存在并发执行的情形;
- 在 Messenger 中进行数据传递必须将数据放到 Message 中,而 Messenger 和 Message 实现了 Parcelable 接口,因此可以跨进程传输;
- Message 中能能使用的载体只有 what、arg1、arg2、Bundle 以及 replyTo;
- Messenger 以串行的方式处理客户端发来的消息;服务端一个一个的处理,不适合大量的并发请求;
- 实际上作用主要是为了传递消息,不适合跨进程调用服务端的方法(这时候需要考虑使用 AIDL)
4. 使用 AIDL #
- 服务端
首先创建一个 Service 用来监听客户端的连接请求,然后创建一个 AIDL 文件,将暴露给客户端的接口在这个 AIDL 文件中声明,最后在 Service 中实现这个 AIDL 接口即可; - 客户端
首先绑定服务端的 Service,绑定成功之后,将服务端返回的 Binder 对象转成 AIDL 接口所属的类型,接着就可以调用 AIDL 中的方法了; - AIDL 接口的创建
创建一个 .aidl 文件,里面声明一个接口与若干个接口方法,AIDL 的接口只支持方法,不支持声明静态变量,有别于传统的接口 - 远程服务端 Service 的实现
实现 AIDL 的接口,首先要创建一个 Service,创建一个 Binder 对象,并在 onBinder 中返回它。AIDL 方法是在服务端的 Binder 线程池中执行的,在 AIDL 方法中处理线程同步; - 客户端的实现
首先绑定远程服务,绑定成功之后将服务端返回的 Binder 对象转换成 AIDL 接口,然后就可以通过这个接口去调用服务端的远程方法了;(AIDL 中无法使用普通接口)
[ 还有几点需要知道 ]
- 对象是不能跨进程直接传输的,对象的跨进程传输本质上都是反序列化的过程,这就是为什么 AIDL 中自定义对象都必须要实现 Parcelable 接口的原因;
- 虽然说多次跨进程传输客户端的同一个对象会在服务端生成不同的对象,但是这些新生成的对象有一个共同点,那就是它们底层的 Binder 对象是同一个;
- 客户端调用远程服务的方法,被调用的方法运行在服务端的 Binder 线程池中,同时客户端线程会被挂起,服务器端方法不能执行耗时的方法(如果是客户端是 UI 线程的话),防止 ANR;
- 客户端的 onServiceConnected 和 onServiceDisconnected 方法都运行在 UI 线程中,所以也不可以在它们里面直接调用服务端的耗时方法;
5. 使用 ContentProvider #
- 专门用于不同应用之间进行数据共享的方式,天生适合进程间通信;
- 和 Messenger 一样,ContentProvider 的底层实现同样也是 Binder,由此可见,Binder 在 Android 系统中很重要;
- 系统封装,无需关心底层细节即可轻松实现 IPC;
- 系统内置了很多 ContentProvider 比如通信录信息、日程表信息等,跨进程访问只需要通过 ContentResolver 的 query、update、insert 和 delete 方法即可;
- 六个抽象方法:onCreate / query / update / insert / delete / getType ;
- ContentProvider 主要以表格的形式来组织数据;也支持文件数据比如,图片、视频等;
- 系统提供的 MediaStore 功能就是文件类型的 ContentProvider;
- query / update / insert / delete 四大方法存在多线程并发访问,此方法内要做好线程同步;
- ContentProvider 支持自定义调用,通过 ContentProvider 的 Call 方法和 ContentResolver 的 Call 方法;
6. 使用 Socket #
- Socket 被称为 “套接字” ,分为
流式套接字
和用户数据报套接字
; - 流式套接字对应着网络中传输控制层的 TCP 协议;
- 用户数据报套接字对应着网络中传输控制层的 UDP 协议;
- Socket 本身可以支持传输任意字节流,实现信息的传输,是一种 IPC 方式;
- 实际上,通过 Socket 不仅仅能实现进程间的通信,还可以实现设备之间的通信(前提是这些设备之间的 IP 地址相互可见);
7. IPC 各方式的优缺点和适用场景
End.
Note by HF.
Learn from 《Android 开发艺术探索》
0 0
- # 读 Android 开发艺术探索 &4
- Android开发艺术探索
- # 读 Android 开发艺术探索 &1
- # 读 Android 开发艺术探索 &2
- # 读 Android 开发艺术探索 &3
- # 读 Android 开发艺术探索 &5
- # 读 Android 开发艺术探索 &6
- # 读 Android 开发艺术探索 &7
- # 读 Android 开发艺术探索 &8
- # 读 Android 开发艺术探索 &9
- # 读 Android 开发艺术探索 &10
- # 读 Android 开发艺术探索 &11
- # 读 Android 开发艺术探索 &12
- # 读 Android 开发艺术探索 &13
- Android开发艺术探索 第4章
- Android 开发艺术探索 读书笔记4
- Android 开发艺术探索读书笔记
- 《Android开发艺术探索》读书笔记
- # 读 Android 开发艺术探索 &3
- QtCreator动态编译jsoncpp完美支持x86和arm平台
- QT中窗体的停靠
- 正则表达式校验
- C++ 头文件系列(iterator)
- # 读 Android 开发艺术探索 &4
- redis使用总结
- NSOPeration NSOperationQueue
- Python文本处理之按行处理大文件
- gitlab的事故告诉我们,备份不是仅仅把数据另写几份到磁盘上
- java.lang.RuntimeException: java.io.IOException: invalid constant type: 15
- 12-另一种helper的使用方法
- 一维数组内存分析及数组元素的创建和使用
- [Maven.Definitive.Guide]读书笔记