介绍
Android进程间通信即IPC(Inter-Process Communication),是指安卓组件在一个应用的两个进程之间通信或者两个应用之间通信的过程。进程间通信的方式主要有:Intent,文件共享,Messenger,AIDL,ContentProvider,Socket等方式。
进程和线程
要了解进程间通信,那首先应该搞清楚什么是进程和线程。
进程是指的一个执行单元,Android中一般是指的一个应用。而线程是CPU调度的最小单元,它是系统中有限的资源,一个进程中可以有多个线程。在Android中,线程主要分为主线程(UI线程)和工作线程,我们要在UI线程中操作界面,在工作线程中执行耗时任务,否则可能会出现ANR即应用无响应。
Android中实现多进程
Android中的组件默认执行在同一个进程中,该进程的名字是应用的包名。如果想启动新的进程,只需要在AndroidManifest中为四大组件指定android:process即可。
<activity
android:name=".SecondActivity"
android:process=":remote" />
<activity
android:name=".ThirdActivity"
android:process="com.m1ku.ipcdemo.remote" />
启动的SecondActivity运行在com.m1ku.ipcdemo:remote进程中,ThirdActivity运行在com.m1ku.ipcdemo.remote进程中。:remote以:开头的是当前应用的私有进程,其他应用的组件不能和它跑在这个进程中,而不以:开头的为全局进程。
Android多进程的问题
- 静态成员和单例模式完全失效
- 线程同步机制完全失效
- SharedPreference的可靠性下降
- Application会多次创建
由于Android会为每一个进程分配一个独立的虚拟机,而不同虚拟机所对应的内存地址是不同的,所以线程同步需要加锁的地方机会失效,而SharedPreference本身不支持两个进程同时执行写操作。系统创建新的进程同时分配独立虚拟机的过程,就是启动一个应用的过程,而这就有Application的创建了。所以,在多进程时,每个进程的组件都对应着单独的虚拟机,内存空间以及Application。
对象的序列化
在使用Intent或者Binder进行进程间通信时,需要将对象序列化。而序列化主要有两种方式,实现Serializable或者Parcelable接口。
Serializable
Serializable接口是Java提供的序列化接口。让对象实现Serializable接口就可以完成对象的序列化。
public class Book implements Serializable {
private static final long serialVersionUID = 5820845440216217905L;
private int id;
private String name;
public Book(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
serialVersionUID是根据当前类的结构生成的id,在序列化时会将它写入到文件或者其他介质中,反序列化时会验证serialVersionUID是否一致,如果不一致的话会反序列化失败。当类结构发生变化,如新增成员时serialVersionUID值就会改变。可以手动指定serialVersionUID的值,以保证反序列化成功。
Parcelable
Parcelable接口是Android提供的序列化接口,通过实现Parcelable接口以及实现相应的方法来完成。
public class Book implements Parcelable {
private int id;
private String name;
public Book(int id, String name) {
this.id = id;
this.name = name;
}
protected Book(Parcel in) {
id = in.readInt();
name = in.readString();
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(id);
parcel.writeString(name);
}
}
writeToParcel完成对象的序列化,CREATOR完成对象的反序列化。其中Parcel对象中包装了可序列化的数据,序列化和反序列化由它的一系列write和read方法完成。
Serializable序列化涉及大量的I/O操作,开销比较大。Parcelable实现序列化效率较高,并且它是Android提供的,所以在Android上一般使用Parcelable接口。