IPC机制
- 指的的是进程间的通信或者跨进程通信,确切的说就是两个进程之间的数据交互的过程!
那么我们使用多进程的的需求一般都是什么?
- 一般是为了增加应用的的可使用内存,安卓对一个应用的最大使用内存做了限制一般是16mb。
我们如何开启多进程呢?
- 我们一般只需要在给使用的组建加上一个android:process属性就行了!
- 第二种我们通过JNI在native层去fork一个新的进程,这种方法属于特殊情况不做处理。
<service android:name=".ServiceA" android:process=":service"></service>
- 在这里
android:process=":service"
这个代表生成的新的进程的名字是包名加上:service并且代表当前的进程是私有的,其他应用组建不能和他跑在一个进程里面,还有一种直接以包名来命名这种不带冒号就是全局的进程,其他应用通过shareuid可以和他跑在一个进程里面!TIP如果共用一个进程就能共享内存中的数据。
导致两个不同进程间通信不了的原因是什么呢?
- android会为每一个应用分配一个独立的虚拟机,或者说为每个进程都分配一个独立的虚拟机,不同的虚拟机在内存上的地址是不一样的所以导致同一个类但是是不同的地址空间。
使用多进程会导致的问题:
- 静态成员和单利模式完全失效(因为都不是共享一个虚拟机当然就没有用了)
- sp的可靠性下降(sp不支持两个进程同时去执行读写操作可能会造成数据的丢失)
- application会多次创建(因为我们单个开通一个进程就相当于又重新开通了一个虚拟机当然所有的都是会再次创建了)
实现跨进程通信的方式有哪些?
- 基于binder的Messenger和AIDL以及socket
序列化
public class Person implements Serializable{
private static final long serialVersionUID = 1L;
protected String name;
protected transient int age;
public Person(){}
public Person(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString()
{
return "this is person:"+"name:"+this.name+"——age:"+this.age;
}
}
//序列化一个对象(可以存储到一个文件也可以存储到字节数组)这里存储到自己数组
public static byte[] serialByte(Object obj)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos;
try {
oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
return baos.toByteArray();
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
//反序列化一个对象
public static Object deSerialByte(byte[] by)
{
ObjectInputStream ois;
try {
ois = new ObjectInputStream(new ByteArrayInputStream(by));
return ois.readObject();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
- serialVersionUID我们通过他来制定序列化的版本,注意其中的静态变量不会参与序列化,和用transient关键字来标记成员变量不参与序列化
- 第二种parcel接口这个是我们android中推荐使用的方法性能比较高
public class MyParcelable implements Parcelable {
private int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData);
}
public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
private MyParcelable(Parcel in) {
mData = in.readInt();
}
}
- 如果需要将对象在网络中传输或者实例化到本地还是推荐使用ser这种方式的!
Binder
- Binder是android中的一个类,他继承了ibinder的接口,从ipc角度来说binder就是android中的一种跨进程通信方式,从android framework角度就是各种Manager的桥梁,从应用层来说是客户端和服务端进行通信的媒介!。
总结传输的方式的具体方法
- binder我们直接通过intent就可以传输了。
- 使用文件共享数据,我们可以将一个对象序列化到本地然后另一端去反序列化就可以了,这种只适合在对数据同步要求不高的进程之间通信使用,并且需要考虑并发的问题!
- sp我们不推荐使用这种方式因为他会在内存中存在缓存,导致数据容易丢失,所以我们更不推荐使用sp
- messager信使他的底层使用的也是aidl,是对他的一个封装!他是一个单行串的消息队列,只能一个一个接受消息!
AIDL支持的文件类型:
socket:
- 称为套接字,是网络通信中的概念,他又分为流式套接字和用户数据报套接字两种,又分别对应网络传输控制层中的TCP和UDP
- Tcp:他是面向连接的协议提供双向稳定的通信功能,实现它需要三次握手,他本身提供了超时重传的机制,因此具有很高的稳定性!
- UDP 是无连接的提供不稳定的单项通信功能,UDP也能进行双向传输但是数据容易丢失,容易丢包!