Android IPC机制

本文不扯其他的,就总结Android IPC机制,下面是IPC几乎所有知识的集合.看不清楚的到这里仔细看
IPC机制 脑图

  • 概念
    • 进程间通信方式
    • 进程与线程区别
      • 1. 进程是资源分配的最小单位, 线程是程序执行的最小单位
      • 2. 进程有自己独立的地址空间, 线程没有, 线程使用相同的地址空间共享数据
      • 3. CPU 切换一个线程比切换进程花费小
      • 4. 创建一个线程比进程开销小
      • 5. 线程占用的资源要比进程少很多
      • 6. 线程之间通信更方便, 进程间通信需要以通信的方式 (IPC) 进行
    • Linux 进程通信方式 (了解)
      • 管道
      • 信号量
      • 消息队列
      • 信号
      • 共享内存
      • 套接字
  • 使用场景
    • 某些模块由于特殊原因需要运行在单独的进程里
    • 加大一个应用可使用的内存
    • 向其他应用获取数据
  • 开启多进程模式
    • 在清单文件中指定: android:process
    • 在 native 层 fork(不常用)
  • 运行机制
    • 每个进程都分配了一个独立的虚拟机, 独立的地址空间, 所以导致不能共享内存
    • 常见问题
      • 1. 静态成员和单例模式完全失效
      • 2. 线程同步机制完全失效
      • 3. SharedPreferences 的可靠性下降
      • 4. Application 会多次创建
  • 序列化
    • Serializable
      • 一般需要手动指定 serialVersionUID, 比如 1L.
      • serialVersionUID 不指定, 系统会自动计算当前类的 hash 值, 序列化时和反序列化时如果 serialVersionUID 不一致会 crash. 如果指定了 serialVersionUID, 即使有新增或者删除字段, 任然能够序列化成功.
    • Parcelable
      • writeToParcel() 序列化, 反序列化由 CREATOR 完成, 内容描述由 describeContents() 完成
    • 两者之间的比较
      • Serializable 是 Java 中的序列化接口, 使用简单, 开销很大. 序列化和反序列化需要大量 I/O 操作. Parcelable 效率很高.
      • 序列化到存储设备或者对象序列化后通过网络传输, 建议选择 Serializable
      • Parcelable 主要用在内存序列化上
  • Binder
    • 可以使用 AIDL(系统提供的快速实现 Binder 的工具) 自动生成代码, 也可以自己写
  • Android 中 IPC 方式
    • Bundle(使用 Intent 中附加的 extras)
      • 非常简单, 方便
      • 使用场景: 直接传递数据
    • 共享文件
      • 简单方便
      • 对象记得序列化
      • 不建议使用 SP 进行进程间通信, 虽然它也是文件, 但是它内存有一定的缓存策略, 内存中有一份 SP 文件的缓存.
      • 使用场景: 由于并发读写存在问题, 适合对数据同步要求不高的进程之间通信
    • Messenger
      • 其实底层是通过 AIDL 实现的, 也就是通过 Binder 来通信的
      • 数据传递必须将数据放入 Message 中
      • 串行方式处理, 一个一个地来
    • AIDL
      • 服务端
        • 首先创建一个 Service, 用来监听客户端的连接请求, 然后创建一个 AIDL 文件, 将暴露给客户端的接口在这个 AIDL 文件中声明, 最后在 Service 中实现这个 AIDL 接口即可
        • 客户端注册的 listener(RemoteCallbackList, 底层是 map,key 是 binder), 服务端调用 listener 中的方法, 这个方法是运行在客户端的 binder 线程中, 可能很耗时, 所以不能在 UI 线程搞
      • 客户端
        • 首先需要绑定服务端的 Service, 绑定成功后, 将服务端返回的 Binder 对象转成 AIDL 接口所属的类型, 接着就可以调用 AIDL 中的方法了.
        • 调用服务端的方法时, 运行在服务端的 binder 线程池中, 不能在 UI 线程调用
      • 客户端与服务端之间传递的对象不是引用, 而是序列化和反序列化了的
    • ContentProvider
      ContentProvider 是 Android 中提供的专门用于不同应用间进行数据共享的方式, 天生适合进程间通信. 底层是 Binder
      • android:authorities 唯一标识
      • onCreate()在主线程中运行, 其他 () 都在 binder 线程中运行
      • 通过 Uri 来区分外面要访问的数据集合, 需要定义单独 Uri 和 Uri_Code, 使用 U 日 Match 而的 addURI() 方法将 Uri 和 Uri_Code 关联到一起
      • update,insert,delete 方法会引起数据源的改变, 这时候需要调用 ContentResolver 的 notifyChange 方法来通知外界当前 ContentProvider 中的数据已经发生改变
      • 观察 ContentProvider 中的数据改变情况, 可以通过 ContentProvider 的 registerContentObserver() 方法来注册观察者, unregisterContentObserver 方法来解除观察者
    • Socket(网络通信肯定是可以的撒)
      • 底层实现分类
        • TCP
          • 稳定
          • 超时重传
          • 三次握手, 四次挥手
        • UDP
          • 无连接
          • 不太可靠, 只保证发出去, 不保证正确传输
          • 效率高
      • 连接上了之后可以互相通信, 不像 Http(是 APP 主动通信, 然后服务端返回).
  • Binder 连接池
    当 aidl 比较多的时候, 需要用到 Binder 连接池, 为了共用一个 Service. 这个 Service 可兼容多个 aidl
    • 我们需要减少 Service 的数量,将所有的 AIDL 放在同一个 Service 中去管理。Binder 连接池用于转发查询应该使用哪个 aidl
  • IPC 优缺点及适用场景
    • Bundle
      • 优点: 简单易用
      • 缺点: 只能传输 Bundle 支持的数据类型
      • 适用场景: 四大组件之间的进程间通信
    • 文件共享
      • 优点: 简单易用
      • 缺点: 不适合高并发场景, 并且无法做到进程间即时通信
      • 适用场景: 无并发访问情形, 交换简单的数据实时性不高的场景
    • AIDL
      • 优点: 功能强大, 支持一对多并发通信, 支持实时通信
      • 缺点: 使用稍复杂, 需要处理好线程同步
      • 适用场景: 一对多通信且有 RPC(远程过程调用) 需求
    • Messenger
      • 优点: 功能一般, 支持一对多串行通信, 支持实时通信
      • 缺点: 不能很好的处理高并发情形, 不支持 RPC, 数据通过 Message 进行传输, 因此只能传输 Bundle 支持的数据类型
      • 适用场景: 低并发的一对多即时通信, 无 RPC 要求, 或者无须要返回结果的 RPC 需求
    • ContentProvider
      • 优点: 在数据访问方面功能强大, 支持一对多并发数据共享, 可通过 Call 方法扩展其他操作
      • 缺点: 可以理解为受约束的 AIDL, 主要提供数据源的 CRUD 操作
      • 适用场景: 一对多的进程间的数据共享
    • Socket
      • 优点: 功能强大, 可以通过网络传输字节流, 支持一对多并发实时通信
      • 缺点: 实现细节稍微有点繁琐, 不支持直接的 RPC
      • 适用场景: 网络数据交换
posted @ 2019-04-19 22:00  潇风寒月  阅读(47)  评论(0)    收藏  举报