IPC基礎概念的介紹
本篇主要是介紹 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
持續更新中。。