IPC机制

Android IPC简介

IPC: Inter-Process Communication, 含义为进程间通信或者跨进程通信,指两个进程之间进行数据交换的过程。

使用场景:多进程

Android中的多进程模式

正常情况下,在Android中多进程是指一个应用中存在多个进程的情况。

使用多进程方法:给四大组件在AndroidManifest中指定android:process属性

“ :name ” 在当前的进程名前面附加上当前的包名,且属于该应用的私有进程,其他应用的组件不可以和它跑在同一进程中;进程名不以:开头,属于全局进程。

全局变量在多进程中并不是共享的(一处修改处处同步),只会影响该进程,但对其他进程中没有影响(也就是说意味着都存在同一个类但互不干扰)

使用多进程会造成的问题:

  1. 静态成员和单例模式失效
  2. 线程同步机制完全失效
  3. SP的可靠性下降
  4. Application会创建多次

IPC基础概念介绍

序列化(Intent, Binder, 对象持久化,网络传输…)

  1. Serializable
    实现 Serializable ,添加 private static final long serialVersionUID = …(手动指定可以很大程度上避免反序列化过程的失败)
    进行对象的序列化和反序列化: ObjectOutputStream , ObjectInputStream
    注意:静态成员变量不属于对象,不会参与序列化过程;使用transient关键字标记的成员变量不参与序列化过程。
    特点:使用简单但开销大,JAVA提供
  2. Parcelable
    在序列化的过程中需要实现的功能:序列化(writeToParcel),反序列化(CREATOR),内容描述(几乎所有情况下都为0,仅当当前对象中存在文件描述时返回1)
    特点:Android提供,效率高但相对会麻烦点
  3. Binder
    Binder是一个类,实现了IBinder接口。
    Binder是Android种一种跨进程的通信方式。
    Binder可以理解为虚拟的物理设备,设备驱动是/dev/binder
    Binder是ServiceManager连接各种Manager(ActivityManager,WindowManager…)和相应的ManagerService的桥梁。
    Binder是客户端和服务端进行通信的媒介。

    Binder类(系统自动生成)分析:
    核心实现是它的内部类Stub和Stub的内部代理类Proxy
    DESCRIPTOR: Binder的唯一标识,一般用当前Binder的完整类名表示;
    asInterface(android.os.IBinder obj) :用于将服务端的Binder对象转换成客户端所需的AIDL接口类型的对象。转换区分进程,若客户端与服务端位于同一进程,则返回服务端的Stub对象本身;否则返回系统封装后的Stub.proxy对象。
    asBinder : 此方法返回当前Binder对象
    onTransact: 该方法运行在服务端中的Binder线程池。

    public Boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)

       //服务端通过code确定客户端请求的目标方法;从data中取出目标方法所需的参数,然后执行目标方法;执行完毕后,向reply中写入返回值;

注意:若远程方法耗时,则客户端不能再UI线程中发起此远程请求;Binder采用同步的方式实现;

为了解决服务端进程由于某种原因异常终止而导致客户端受影响,Binder中提供了两个配对的方法:
linkToDeath() and unlinkToDeath()
linkToDeath()给binder设置死亡代理,需要传入DeathRecipient实现类(当Binder死亡时,系统会回调DeathRecipient接口中的binderDied()方法,在该方法中调用unlinkToDeath()并重新绑定远程的service)

Android中的IPC方式

  1. 使用Bundle
    三大组件(Activity, Service, Receiver)都支持在Intent中传递Bundle数据,Bundle实现了Parcelable,所以可以在不同的进程间传输。
    使用场景:1)典型的传递数据;2)把原本需要在A进程中进行的计算任务转移到B进程的后台Service中去执行;
    问题:支持的类型限制
  2. 使用文件共享
    两个进程通过读写同一个文件(文本信息/序列化对象)来交换数据
    问题:并发读写的问题;不建议使用SP,由于系统对它的读写有一定的缓存策略,即在内存中会有一份SP文件的缓存。
  3. 使用Messenger
    轻量级的IPC方案,底层实现是AIDL。
    实现的步骤:1)服务端进程,创建一个Service来处理客户端的请求,同时创建一个Handler并通过它创建一个Messenger对象,然后在Service的onBind中返回这个Messenger对象底层的Binder。2)客户端绑定Service,用返回的IBinder对象创建一个Messenger,通过Messenger向服务端发送消息。
    注意:在Messenger中进行数据传递必须将数据放入Message。而Messenger,Message都实现了parcelable接口。Message中所支持的数据类型就是Messenger所支持的传输类型。Message载体中有:what, arg1, arg2, Bundle以及replyTo,object

    场景:以串行的方式处理客户端的消息,不适合大量的并发请求,主要作用仍是传递消息。
  4. 使用AIDL
    流程:1)服务端创建一个Service用来监听客户端连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中申明,最后返回的Binder继承自AIDL接口.2)客户端需绑定Service,将返回的Binder对象转换成AIDL接口所属的类型,接着调用AIDL中的方法。
    通过AIDL实现观察者模式,无法实现解注册!原因是:AIDL中自定义的对象本质上都是反序列的过程,也就是说Binder会把客户端传递过来的对象重新转化并生成一个新的对象。实现解注册,使用RemoteCallbackList(系统专门提供的用于删除跨进程listener的接口),是一个泛型,支持管理人一的AIDL接口
    public class RemoteCallbackList<E extends IInterface>;

工作原理:内部有一个Map结构专门保存所有的AIDL回调。

     ArrayMap<IBinder, Callback> mCallbacks = new ArrayMap<IBinder, Callback>;

跨进程传输客户端的同一个对象会在服务端生成不同的对象,但是这些对象有一个共同的特点,它们的底层Binder对象是同一个。
5. 使用ContentProvider

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值