本文為Android的IPC相關(guān)知識(shí)整理,具體參考了
- 《Android開發(fā)藝術(shù)探索》第二章 IPC機(jī)制
IPC拣凹,Inter-Process Communicatoin的縮寫。即為Android進(jìn)程間通信。
1,進(jìn)程與線程
- 線程是CPU調(diào)度的基本單位忘衍,進(jìn)程一般指一個(gè)執(zhí)行單元,在移動(dòng)設(shè)備上指一個(gè)應(yīng)用或者是一個(gè)程序卿城。一個(gè)進(jìn)程包含一個(gè)或多個(gè)線程枚钓。
- 在Android中,一個(gè)程序可以只有一個(gè)線程瑟押,即主線程搀捷,也叫UI線程。在UI線程中才能操作界面元素勉耀,而不能在UI線程中執(zhí)行大量耗時(shí)任務(wù),否則會(huì)造成ANR蹋偏,Application not responding錯(cuò)誤便斥。
Android線程(Thread)間通信:
- Handle和Looper配合,消息隊(duì)列機(jī)制威始。我們可以用AsyncTask類這個(gè)異步任務(wù)類枢纠。
- 訪問其他應(yīng)用程序的Activity,通過Intent附帶信息
IntentcallIntent= newIntent(Intent.ACTION_CALL,Uri.parse("tel:12345678");
startActivity(callIntent); - ContentProvider黎棠,例如訪問系統(tǒng)相冊(cè)晋渺,通訊錄镰绎,短信等
- Broadcast 廣播
- AIDL,Android接口定義語言
Android進(jìn)程(Process)間通信:
- Binder
- Socket
- 文件共享
- ContentProvider
- Intent
- Messenger
2木西,Android中的多進(jìn)程
在Android中使用多進(jìn)程只有一種方法畴栖,即給四大組件在AndroidManifest中指定android:process屬性。
<activity
android:name="com.ryg.chapter_2.MainActivity"
android:label="@string/app_name">
<intent-filter>
....
</intent-filter>
</acitivty>
<activity
android:name="com.ryg.chapter_2.SecondAcitvity"
android:process=":remote"/>
<activity
android:name="com.ryg.chapter_2.ThirdAcitvity"
android:process="com.ryg.chapter.remote"/>
以上三個(gè)activity分別在以下進(jìn)程中:
- com.ryg.chapter_2八千,沒有為組件指定process吗讶,那么這個(gè)組件就會(huì)運(yùn)行在默認(rèn)進(jìn)程中。
- com.ryg.chapter_2:remote恋捆,冒號(hào)的含義是在當(dāng)前的進(jìn)程名上附加當(dāng)前的包名照皆,此進(jìn)程屬于當(dāng)前應(yīng)用的私有進(jìn)程。
- com.ryg.chapter_2.remote沸停,進(jìn)程名不以冒號(hào)開頭的進(jìn)程屬于全局進(jìn)程膜毁,其他應(yīng)用通過ShareUID方式可以和它跑在同一個(gè)進(jìn)程中。
由于Android會(huì)為每一個(gè)進(jìn)程提供單獨(dú)的虛擬機(jī)愤钾,不同的虛擬機(jī)在內(nèi)存分配上有不同的地址空間瘟滨,因而在不同的虛擬機(jī)中訪問同一個(gè)類對(duì)象會(huì)產(chǎn)生多份副本。不同進(jìn)程的虛擬機(jī)绰垂,Application室奏,內(nèi)存空間都不一樣!>⒆啊k誓!相當(dāng)于兩個(gè)不同的應(yīng)用采用了SharedUID模式占业。
多進(jìn)程引起的問題:
- 靜態(tài)成員和單例模式失效
- 線程同步機(jī)制失效
- SharedPreferences可靠性下降绒怨,其不支持兩個(gè)進(jìn)程同時(shí)執(zhí)行寫操作。
- Application會(huì)多次重建
3谦疾,IPC基礎(chǔ)概念
當(dāng)我們需要通過Intent和Binder傳輸數(shù)據(jù)時(shí)南蹂,需要使用Serializable和Serializable接口來完成對(duì)象的序列化。
當(dāng)我們需要使對(duì)象持久化到存儲(chǔ)設(shè)備上時(shí)念恍,需要使用Serializable來完成對(duì)象的持久化六剥。
3.1 Serializable接口
這個(gè)是Java自帶的,很簡(jiǎn)單但是內(nèi)存開銷大峰伙,只需要在類中加入serialVersionUID疗疟。適用于將對(duì)象序列化到存儲(chǔ)設(shè)備或者將對(duì)象序列化后通過網(wǎng)絡(luò)進(jìn)行傳輸。
public class User implements Serializable{
private static final serialVersionUID = 4132904873290147032L;
public int userId;
public String userName;
public boolean isMale;
}
序列化和反序列化過程
//序列化
User user = new User(0, "jake",true;);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("cache.txt"));
out.writeObject(user);
out.close();
//反序列化
ObjectInputStream in= new ObjectInputStream(new FileInputStream("cache.txt"));
User newUser = (User)in.readObject();
in.close();
恢復(fù)后的newUser對(duì)象和user內(nèi)容完全一致瞳氓,但不是同一對(duì)象策彤。
為了避免反序列化失敗,serialVersionUID 一般應(yīng)該手動(dòng)指定!5晔裹刮!其實(shí)也可以不指定serialVersionUID ,但這樣的話是IDE自動(dòng)根據(jù)類結(jié)構(gòu)去生成hash值庞瘸,這樣的話我們對(duì)其的控制力就弱了捧弃,如果改變了類結(jié)構(gòu),就不能反序列化了K≈蕖K稹!霜第!而手動(dòng)指定serialVersionUID 可以最大限度恢復(fù)數(shù)據(jù)葛家。
3.2 Parcelable接口
這個(gè)是Android獨(dú)有的,更適合用在Android平臺(tái)泌类,效率高癞谒,但是用起來有點(diǎn)麻煩。
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;
}
public Book book;
//內(nèi)容描述
public int describeContents(){
return 0;
}
//序列化
public void writeToParcel(Parcel out, int flags){
out.writeInt(userId);
out.writeString(userName);
out.writeInt(isMale ? 1 : 0);
out.writeParcelable(book, 0 );
}
//反序列化
public static final Parcelable.Creator<user> CREATOR = new Parcelable.Creator<User>(){
//從序列化后的對(duì)象中創(chuàng)建原始對(duì)象
public User createFromParcel(Parcel in){
return new User(in);
}
//創(chuàng)建指定長(zhǎng)度的原始對(duì)象
public User[] newArray(int size){
return new User[size];
}
};
private User(Parcel in){
userId = in.readInt();
userName = in.readString();
isMale = in.readInt() = 1;
book = in.readParcelable(Thread.currentThread().getContextClassLoader());
}
}
3.3 Binder
- 從IPC角度看刃榨,Binder是一種跨進(jìn)程通信方式弹砚。
- 從Android Freamwork角度來說,Binder是ServiceManager連接各種Manager(ActivityManager枢希、WindowManager)和相應(yīng)ManagerService的橋梁桌吃。
- 從Android應(yīng)用層將,Binder是客戶端和服務(wù)器進(jìn)行通信的媒介苞轿。
Android開發(fā)中茅诱,Binder主要用在Service中,包括AIDL搬卒,Messenger瑟俭。