安卓开发博客

Android 开发艺术探索之二 -- IPC 机制

2018-07-12  本文已影响8人  whd_Alive

学习内容:(IPC 机制)

1. IPC 简介

2. Android 的多进程模式

3. IPC 基础概念介绍

4. Android 中的 IPC 方式

  1. Bundle

    1. 范围:Activity、Service、Receiver 支持在 Intent 中传递 Bundle 数据
    2. 原理:Bundle 实现了 Parcelable 接口
    3. 限制:传递的数据必须能够被 序列化
  2. 文件共享

    1. 范围:适合在对数据同步要求不高的进程之间进行通信,并且要妥善处理并发读写的问题。可以传递文本文件,其包含文本信息,或者序列化对象,也可以是 XML 文件

    2. 原理:两个进程通过 读/写同一个文件来交换数据

    3. 限制:要尽量避免并发写这种情况或者考虑使用线程同步来限制多个线程的写操作。

      SharedPreferences 不适合用于进程间通信,原因如下:

      系统对 SharedPreferences 的读/写有缓存策略,即内存中有 SharedPreferences 文件的缓存,因此多进程模式下,系统对 SharedPreferences 的读写不可靠

  3. Messenger:

    1. 范围:轻量级的 IPC 方案,主要用于传递消息

    2. 原理:底层实现是 Binder

    3. 限制:串行处理,一次处理一个请求,不适合高并发情形

    4. 使用:

      1. 服务端进程

        创建一个 Service 来处理客户端的连接请求,同时创建一个 Handler 并通过它来创建一个 Messenger 对象,然后在 Service 的 onBind 方法中返回底层的 Binder 即可。

      2. 客户端进程

        绑定服务端的 Service,通过返回的 IBinder 对象创建 Messenger,以此发送 Message 类型消息。

  4. AIDL

    1. 范围:处理大量的跨进程并发请求

    2. 原理:Binder

    3. 限制:线程同步的问题

    4. 使用:

      1. 服务端

        首先创建 Service 监听客户端的连接请求,然后创建 AIDL 文件,并在此 AIDL 文件中声明暴漏给客户端的接口,最后在 Service 种实现这个 AIDL

        接口即可

      2. 客户端

        绑定服务端的 Service,之后将返回的 Binder 对象转换成 AIDL 接口所属的类型,之后调用相应的方法

      3. 支持的数据类型

        1. 基本数据类型(int、long、char、boolean、double等)
        2. String 和 CharSequence
        3. List:只支持 ArrayList
        4. Map:只支持 HashMap
        5. Parcelable:所有实现Parcelable 接口的对象
        6. AIDL:所有的 ADL 接口本身也可以在 AIDL 文件中使用
    5. 注意事项

      1. 自定义的Parcelable 对象必须创建一个同名的 AIDL 文件,并声明为 Parcelable 类型,并 improt 进来
      2. 建议将所有和 AIDL 相关的类和文件都放入同一个包中,方便把整个包复制到客户端工程中。
      3. CopyOnWriteArrayList 支持并发读/写代替直接使用 ArrayList,类似的使用 ConcurrentHashMap 代替直接使用 HashMap
      4. RemoteCallbackList 是系统专门提供的用于删除跨进程 listener 的接口。RemoteCallbackList 是一个泛型,支持管理人一的 AIDL 接口,原理是内部持有一个 Map 结构专门用来保存所有的 AIDL 回调,其中 value:Callback 封装了真正的远程 listener
      5. 远程被调用的方法运行在服务端的 Binder 线程池中,同时客户端线程挂起,因此需要在子线程调用远程耗时方法。
      6. 客户端 onServiceConnected 和 onServiceDisconnected 方法运行在 UI 线程,不可直接调用远程耗时方法
      7. 服务端方法本身运行在服务端的 Binder 线程池,因此本身就可以执行耗时操作,此时不建议开线程进行异步任务
    6. 权限验证

      1. 在 onBind 中进行验证,不通过直接返回 null -> 应用无法绑定到我们的服务
      2. 在 onTransact 中验证,不通过直接返回 false -> 客户端请求失败,服务端不执行 AIDL 的方法。
      3. 具体验证方式:
        1. permission 验证
        2. Uid 和 Pid 验证
  5. ContentProvider

    1. 范围:专门用于不同应用间数据共享的方式,以表格形式组织数据,可以包含多个表,同时也支持文件数据,比如图片、视频等。
    2. 原理:Binder
    3. 限制:线程同步的问题
    4. 使用:例子看书吧。
    5. 注意事项
      1. android:authorities 和 android:permission 属性
      2. 通过 ContentResolver 的 notifyChange() 方法通知数据发生改变。
  6. Socket

    1. 范围/原理:通过网络传输字节流
    2. 流式套接字 -> TCP;用户数据报套接字 -> UDP
    3. 注意事项:
      1. 不能在主线程访问网络

5. Binder 连接池

  1. 原因:避免随着项目变得庞大之后,无限制的根据 AIDL 增加 Service,使得增加系统资源的开销。此时将所有的AIDL 放在同一个 Service 中管理。

  2. 工作机制:每个业务模块创建自己的 AIDL 接口并实现此接口,此时不同模块间不能存在耦合,单独实现细节,然后向服务端提供自己的唯一标识和对应的 Binder 对象;对于服务端,只需要一个 Service,服务端提供一个 queryBinder 接口,该接口根据业务模块的特征返回 Binder 对象,不同的业务模块拿到所需的 Binder 对象即可调用远程方法。

    由此可见:Binder 连接池的主要作用就是将每个业务模块的 Binder 请求统一转发到远程 Service 中去执行。

  3. 注意事项:

    1. BinderPool 采用单例实现
    2. BinderPool 存在断线重连机制,当远程服务意外终止时,BinderPool 会重新建立连接,此时如果业务模块的 Binder 调用出现异常,则需要手动重新获取最新的 Binder 对象

6. 合适的 IPC 方式

IPC 方式的优缺点和适用场景
上一篇 下一篇

猜你喜欢

热点阅读