简介
Inter-Process Communication。进程间通信,指两个进程之间进行数据交互的过程。
进程:指一个执行单元,在PC或者移动设备上指一个程序或者是一个应用。同一个进程里内存资源是共享的,不同进程里的资源是不共享的。一个进程中至少要包含一个线程,在Android中指的就是主线程,即UI线程。
线程:线程是CPU调度的最小单元。
创建进程
创建一个进程很简单,只需要在Androidmenifest中添加process标签,就可以创建一个进程,命名格式一般为包名,如:android:process="com.example.w"
android:process=":w"
- ":"会在当前的进程名前面附加上当前的包名,创建的进程属于当前应用的私有进程,其他应用不可以与其运行在同一进程
- 不以“:”开头的进程属于全局进程,其他进程可以通过shareUID的方式与其运行在同一进程(签名相同)
进程的等级
- 前台进程;用户正在使用的进程,简单理解就是用户正在交互的对象。一直存在的前台进程是极少的,而且前台进程一般是最后内存小的连前台进程都没有地方运行的时候,才会杀掉进程。
- 可见进程:如弹出一个对话框的Acitivity,后面的Activity是可见的。后面可见的Activity可以被认为是一个可见进程。
- 服务进程:一个通过startService()启动的service,用户虽然看不到然而进行着和用户关注的任务,如下载,播放音乐
- 后台进程:按了home键之后不可见的activity,一般是执行了onStop()方法之后,在内存不足的情况下可能会被回收
- 空进程:里面没有任何可以运行的程序组件,这些进程存在就是作为一个缓存,为下一次启动程序缩短时间。
多进程的优点
- 稳定安全:一个子进程如果因为某些异常结束之后,不会直接导致主程序的崩溃。
- 扩大内存空间:android系统对于一个应用程序的内存占用是有限制的,当使用多进程的时候,可以减少主进程占用的内存,这样降低被系统kill的概率。
多进程带来的问题
- 静态成员和单例模式完全失效
- 线程同步机制完全失效
- sharedPreferences的可靠性降低
- Application会多次创建
第三个问题是因为:sharedPreferences不支持两个进程同时去执行写操作,否则有一定几率造成数据的丢失;
第四个问题是因为:不同进程的组件会拥有独立的虚拟机、内存空间、Application。
同一个应用的多进程可以理解为:两个不同应用采用了shareUID的模式
Serializable接口
Serializable是Java中的一个序列化接口,为对象提供标准的序列化和反序列化操作。创建实现Serializable接口的类,serialVersionUID 用于辅助序列化和反序列化
public class User implements Serializable{
private static final long serialVersionUID = 123456789L;
public int userId;
public String userName;
public boolean isMale;
public User(int userId, String userName, boolean isMale) {
this.userId = userId;
this.userName = userName;
this.isMale = isMale;
}
}
序列化
User user = new User(0, "coco", true);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
out.writeObject(user);
out.close();
反序列化
ObjectInputStream in = new ObjectInputStream(new FileInputStream("cache.txt"));
User user = (User) in.readObject();
in.close();
注意:1、得到的对象和之前的对象内容完全一样,但是属于不同的对象
2、静态成员属于类不属于对象,不参与序列化;使用transient关键字标记的成员变量不参与序列化
Parcelable接口
Android提供的实现序列化与反序列化的接口。
实现序列化与反序列化代码示例
public class User implements Parcelable{
public int userId;
public String userName;
public boolean isMale;
public User(int userId, String userName, boolean isMale) {
this.userId = userId;
this.userName = userName;
this.isMale = isMale;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(userId);
dest.writeString(userName);
dest.writeByte((byte) (isMale ? 1 : 0));
}
public static final Creator<User> CREATOR = new Creator<User>() {
@Override
public User createFromParcel(Parcel in) {
return new User(in);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
protected User(Parcel in) {
userId = in.readInt();
userName = in.readString();
isMale = in.readByte() != 0;
}
}
在上述代码中,实现的功能主要有序列化、反序列化、内容描述。序列化功能主要由writeToParcel方法完成,最终通过Parcel的一系列write方法来完成;反序列化过程由CREATOR完成,其内部标明了如何创建序列化对象和数组,并通过Parcel的一系列read方法来完成反序列化过程。内容描述功能由describeContents方法来完成,几乎在所有情况下这个方法都返回0,仅当当前对象中存在文件描述符时,此方法返回1.