IPC

264 阅读3分钟

IPC概念

  1. 使用多进程:android:process属性

  2. Android为每一个进程都分配一个独立的虚拟机,导致在不同的虚拟机中访问同一个类的对象会产生多份副本,即使是public static int sUerId = 1之类的静态变量也一样

  3. 使用多进程会造成:

    • 静态成员和单例模式完全失效
    • 线程同步机制完全失效
    • SharedPreferences的可靠性下降
    • Application多次创建
  4. Serializable接口

    1. 要想让一个对象序列化,只需要这个类实现Serializable接口并声明一个serialVersionUID即可
  5. Parcelable接口

    1. 实现decribleContents方法,writeToParcel方法,和CREATOR
  6. Binder

Android实现IPC的方式

  1. 使用Bundle

  2. 使用文件共享

    • 有局限性,比如并发读写
    • 文件共享的方式适合在对数据同步要求不高的进程间进行通信,并且要妥善处理并发读写的问题
    • 不建议在进程间通信使用SharedPrefetences
  3. 使用Messenger

    • 只能串行的方式处理客户端发来的信息
    1. 服务端进程
      • 我们需要在服务端创建一个Service,同时创建一个Handler并通过它来创建一个Messenger对象,然后在Service的onBind中返回这个Messenger对象底层的Binder即可
    2. 客户端进程
      • 首先绑定服务端的Service,绑定成功后用服务端返回的IBinder对象创建一个Messenger,通过这个Messenger就可以向服务端发送消息了,发送消息类型为Message对象。这就实现了客户端到服务端的通信
      • 如果想要服务端回应客户端。需要在客户端创建一个Handler并创建一个新的Messenger,并把这个Messenger对象通过Message的replyTo参数传递给服务端,服务端通过这个replyTo参数就可以回应客户端
  4. 使用AIDL

    • AIDL是日常开发涉及进程间通信时的首选
    1. 服务端
      • 首先创建一个Service,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中,创建一个类继承自AIDL接口中的Stub类并实现Stub中的抽象方法,在Service的onBind方法中返回这个类的对象
    2. 客户端
      • 绑定Service,将服务端返回的Binder对象转成AIDL接口所属的类型,接着就可以调用AIDL中的方法了
    • 拓展:
      • 使用观察者模式,让服务端为被观察者,客户端为观察者
      • 用RemoteCallbackList来实现删除跨进程listener接口
      • 服务端进程意外停止,需要重连服务
        1. 给Binder设置DeathRecipient接听
        2. 或者在onServiceDisconnected中重连远程服务
      • 如何在AIDL中使用权限验证功能
        1. 可以在onBind中进行验证
        2. 在服务端的onTransact中进行验证
      • 用Binder连接池,将所有AIDL放在同一个Service中去管理
  5. 使用ContentProvider

  6. 使用Socket(“套接字”)

    1. Socket称为“套接字”,分为流式套接字和用户数据报套接字,分别对应于网络传输控制层中的TCP和UDP协议
名称 优点 缺点 使用场景
Bundle 简单 只能传输Bundle支持的数据类型 四大组件之间进程通信
文件共享 简单 不适合高并发,无法做到进程间即时通信 无并发访问情形
AIDL 一对多并发即时通信 一对多通信且有RPC需求
Messenger 一对多串行通信,支持实时通信 不能处理好高并发,不支持RPC, 低并发的一对多即时通信,无RPC需求
ContentProvider 支持一对多并发数据共享, 理解为受约束的AIDL,主要提供CRUD操作 一对多进程间的数据共享
Socket 功能强大,通过网络传输字节流,支持一对多并发实时通信 不支持直接RPC 网络数据交换

参考:《Android开发艺术探索》