1. Android IPC 簡介
IPC 全稱是 Inter-Process Communication ,叫做進程間通信或者跨進程通信,是指兩個進程之間進行數(shù)據(jù)交換的過程。
進程 一個進程就是一個正在執(zhí)行程序的實例,包括程序計數(shù)器、寄存器和變量的當前值,堆棧指針、內(nèi)存分配狀況、所打開的文件的狀態(tài)、賬號和調(diào)用信息,以及其他在進程由運行態(tài)轉(zhuǎn)換到就緒態(tài)或阻塞態(tài)時必須保存的信息,從而保證該進程隨后能再次啟動就像從未被中斷過一樣。
線程 線程則是進程的一個實體,是 cpu 調(diào)度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程自己呢基本上是不擁有系統(tǒng)資源的,只擁有一點在運行中必不可少的資源(比如說程序計數(shù)器、一組寄存器和棧),但是它可以與同屬于一個進程的其它線程共享進程所擁有的全部資源。
一個進程可以有很多個線程,也就是進程包含線程。
2. Android 進程間通信的方式
Android 中最有特色的進程間通信方式就是 Binder,除了 Binder,還有 Socket、Intent、共享文件、SharePrefrence、廣播、基于 Binder 的Messenger 和 AIDL。Socket 可以實現(xiàn)任意兩個終端之間的通信,也可以實現(xiàn)一個設(shè)備上任意兩個進程之間的通信。
3. Android 進程間通信的場景
要使用 IPC ,就必須在多進程的場景下。
一個應(yīng)用由于某些原因自身需要采用多進程模式實現(xiàn)
當一個應(yīng)用需要向其他應(yīng)用獲取數(shù)據(jù),如 ContentProvider
4. Android 使用多進程的好處
穩(wěn)定性:子進程的崩潰閃退不會影響主進程
不占用主進程的內(nèi)存,如一些大圖展示
安全隔離,不會因為子進程的安全漏洞危害主進程;
基于多進程可以做到 Activity 級別的?;?。
5. 使用多進程會出現(xiàn)的問題
在 Android 中,系統(tǒng)為每一個應(yīng)用都分配了一個獨立的虛擬機,或者說(重點來啦?。。。槊總€進程都分配一個獨立的虛擬機,不同的虛擬機在內(nèi)存分配上有不同的地址,這就導(dǎo)致不同虛擬機中訪問用一個類的對象會產(chǎn)生多份副本。所以多進程沒有辦法通過共享內(nèi)存來共享數(shù)據(jù),必須通過中間層來共享數(shù)據(jù)。
一般來說,會有以下問題:
- 靜態(tài)變量和單例模式完全失效
- 線程同步機制完全失效
- SharePrefrence 的可靠性降低
- Application 會多次創(chuàng)建
6. 對象的序列化
序列化就是將內(nèi)存中的對象轉(zhuǎn)換成二進制數(shù)據(jù),進而進行網(wǎng)絡(luò)傳輸或者寫入文件保存。Android 使用 Serializable 接口和 Parcelable 接口實現(xiàn)序列化,當我們需要用 Intent 或者 Binder 傳輸數(shù)據(jù)時就需要序列化。
6.1 Serializable 接口
這個接口是一個空接口,使用 Serializable 來實現(xiàn)序列化非常簡單,只需要在類的聲明中指定一個類似下面的標識就可以自動實現(xiàn)默認的序列化過程。
private static final long serialVersonUID = 1L;
//舉例說明:序列化過程
User user = new User(0,"jake",true);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
out.writeObject(user);
out.close();
//舉例說明:反序列化過程
ObjecInputStream in = new ObjectInputStream(new FileInputStream("cache.txt"));
User newUser = (User)in.readObject("cache.txt");
in.close();
注意:恢復(fù)后的 User 對象和原來序列化的那個 User 對象是不同一個,兩個對象的內(nèi)容一樣而已。
原則上序列化后的數(shù)據(jù)中的 serialVersonUID 只有和當前類的 serialVersonUID 相同才能正常地被反序列化。
靜態(tài)類成員變量屬于類,不屬于對象,所以不會參加序列化過程,其次用 transient 標記的成員變量也不會參與序列化。
6.2 Parcelable 接口
實現(xiàn) Parcelable 接口也可以實現(xiàn)序列化。
public Book(Parcel in) {
name = in.readString();
price = in.readInt();
}
// 反序列化功能
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel source) {
return new Book(source);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
@Override
public int describeContents() {
return 0;
}
//序列化功能
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(price);
}
/**
* 參數(shù)是一個Parcel,用它來存儲與傳輸數(shù)據(jù),如果需要讀取數(shù)據(jù),也要寫上這個方法
* @param dest
*/
public void readFromParcel(Parcel dest){
//注意,此處的讀值順序應(yīng)當是和writeToParcel()方法中一致的
name = dest.readString();
price = dest.readInt();
}
系統(tǒng)為我們提供了很多實現(xiàn)了 Parcelable 接口的類,如 Intent、Bundle、Bitmap,還有 List 和 Map,前提是里面的每個元素都可以序列化。
6.3 Serializable 和 Parcelable 對比
Serializable 是 Java 的序列化接口,使用起來簡單但是開銷很大,序列化和反序列化都需要大量的 I/O 操作。而 Parcelable 是 Android 中的序列化方式,效率很高,就是使用麻煩,一般在 Android 平臺首選 Parcelable。