本篇主要是介绍 IPC 中的一些基础概念,主要包括以下三个方面的内容:
- Java 中 Serializable 接口
- Android 中 Parcelable 接口
- Binder
熟悉完这三个方面内容后,才可以更好的理解跨进程通信的各种方式。Serializable 接口和 Parcelable 接口可以完成对象的序列化过程,当我们需要通过 Intent 和 Binder 传输数据时就需要使用 Serializable 接口或者 Parcelable 接口。当我们需要把对象持久化到存储设备上或者通过网络传输给其他客户端,也要使用 Serializable 来完成对象持久化。
1. Java 中 Serializable 接口
Serializable 是 java 提供的一个序列化接口,它是一个空接口,为对象提供标准的序列化和反序列化的操作;接下来先自定义一个 User 类,让它实现 Serializable 接口,它是可以被序列化和反序列化的,下面是 User 类的代码:
public class User implements Serializable {
private static final long serialVersionUID = -521164L;
public int userId;
public String userName;
public boolean isMale;
public User(int i, String bob, boolean b) {
this.userId = i;
this.userName = bob;
this.isMale = b;
}
}
通过 Serializable 方式来实现对象的序列化,实现起来非常简单。下面就用 ObjectOutputStream 和 ObjectInputStream 实现对象的序列化和反序列化,代码如下:
public static void main(String[] args) {
//Java 序列化
try {
User user = new User(0, "Bob", true);
FileOutputStream fos = new FileOutputStream("serialize.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(user);
oos.close();
System.out.println("序列化结束");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//Java 反序列化
try {
FileInputStream fis = new FileInputStream("serialize.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
User newUser = (User) ois.readObject();
System.out.println(newUser);
ois.close();
System.out.println("反序列化结束");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
上面用很简单的代码演示了 Serializable 序列化和反序列化的过程。在 User 类中 serialVersionUID 参数具有什么含义呢???
这个参数是用来辅助序列化和反序列化过程的。serialVersionUID 的工作机制是这样的:序列化的时候系统会把当前类的 serialVersionUID 写入序列化文件中,当反序列化的时候会系统自动检测文件中的 serialVersionUID ,看它是否和当前类的 serialVersionUID 一致,如果一致则可以成功的反序列化;否则会报错而无法进行反序列化。
2. Android 中 Parcelable 接口
上面介绍了通过 Serializable 方式实现序列化的方法, 下面介绍另一种序列化方式: Parcelable 。实现 Parcelable 接口,一个类的对象就可以实现序列化并可以通过 Intent 和 Binder 传递。下面来看具体代码:
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.isMale = isMale;
this.userName = userName;
}
//从序列化后的对象中创建原始对象
protected User(Parcel in) {
userId = in.readInt();
userName = in.readString();
isMale = in.readByte() != 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];
}
};
@Override
public int describeContents() {
return 0;
}
//i为1当前对象需要作为返回值返回,几乎所有情况都为0;
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(userId);
parcel.writeString(userName);
parcel.writeByte((byte) (isMale ? 1 : 0));
}
}
这样便实现了序列化和反序列化;下面我们来用 Intent 实现由 MainActivity 到 TwoActiity 的传值,下面是 MainActivity 的 代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 封装数据
User user = new User(10,"大猫",true);
// 用Intent传递Person对象
Intent i = new Intent(this, TwoActivity.class);
i.putExtra("user", user);
startActivity(i);
}
下面是 TwoActivity 的代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
User user = getIntent().getParcelableExtra("user");
Log.e("==userId", user.userId+"");
Log.e("==userName", user.userName+"");
Log.e("==isMale", user.isMale+"");
}
上面就是 Parcelable 接口的使用和用 Intent 的传值。下面是打印的结果:
可以看出,传值成功;
在选用时,如果时 Android 开发应当首选 Parcelable 。
3. Binder
持续更新中。。