跨程序通信基礎篇
含義:
跨程序通信,是指兩個程序之間資料交換的過程,英文全稱 Inter-Process Communication 縮寫IPC
程序和線程的關系:
在移動裝置上,一個程式或者一個應用,就是一個程序,一個程序裡面可以包含多個線程
(例如:一個應用裡面有一個主線程(用于更新UI)和多個子線程(執行耗時的任務))
開啟多線程的方法:
在Android中開啟多程序隻有一種方法: 那就是給4大元件(Activity,Service,Receiver,ContentProvider)在Menifest中指定android:process屬性,除此之外沒有其他的方法(通過JNI在native層去fork一個新程序除外)
執行個體1如下:
<activity
android:name=".activity.Main2Activity"
android:process=":remote1" />
執行個體2如下:
<activity
android:name=".activity.Main3Activity"
android:process="com.hlj.demo.remote2" />
說明:
1.首先執行個體1中 ":“的含義是指:這是一種簡寫
a.目前的程序名稱前面要附加上目前的包名 程序完整名稱:com.hlj.demo:remote1
b.以”:"開頭的程序屬于目前應用的私有程序,其他應用的元件不可以和它跑在同一個程序中
2,執行個體2中的程序名稱是一種完整的命名方式,不會附加包名資訊,其次它屬于全局程序,其他應用通過ShareUID方式可以和它跑在同一個程序中.(2個應用的簽名也要相同)
注意:
程式入口MainActivity,預設沒有給它process屬性,那麼它就運作在預設的程序中,預設的程序名稱是包名,如果給它指定了process屬性,那麼它就運作在該指定程序當中
如何檢視自己開啟了多少個程序呢,studio如下圖所示:

運作在同一個程序中的元件是屬于同一個虛拟機和同一個Application,可以共享Applicaiton下的資料,運作在不同程序中的元件是屬于2個不同的虛拟機和2個不同的Application,2個不同的Application資料是不能互通的
IPC的基礎概念: Serializable接口,Parcelable接口,Binder
Serializable接口:Serializable是java所提供的一個序列化的接口,它是一個空接口,為對象提供序列化和反序列化操作
//實作Serializable接口即可
public class UserBean implements Serializable{
private static final long serialVersionUID=1L;
public String name;
}
UserBean user = new UserBean();
user.name = "hao123";
if (!StrUtils.IsKong(Environment.getExternalStorageDirectory() + "/" + "demo")) {
String baseExternalStoragepath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "demo";
baseDirectory = new File(baseExternalStoragepath);
if (!baseDirectory.exists()) {
//先建立檔案夾
baseDirectory.mkdirs();
}
//再建立檔案
File wejian = new File(baseDirectory.getPath() + "/" + "user.txt");
if (!wejian.exists()) {
wejian.createNewFile();
}
//序列化到檔案中
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(wejian));
out.writeObject(user);
out.flush();
out.close();
}
//反序列化,從檔案中讀取檔案
File wejian=new File(baseDirectory.getPath()+"/"+"user.txt");
ObjectInputStream in=new ObjectInputStream(new FileInputStream(wejian));
UserBean user=(UserBean)in.readObject();
in.close();
注意:
序列化和反序列化需要讀寫檔案,是以需要在清單檔案配置讀寫權限,大于6.0的裝置還要動态申請權限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
serialVersionUID:
一般來說我們應該手動指定serialVersionUID的值,這樣做的好處是:當版本更新後,我們可能删除了某個成員變量也可能增加了一些新的成員變量,但指定了這個值以後,反序列化還是可以成功,程式可以最大限度的恢複資料,如果不指定serialVersionUID的值的話,程式會挂掉,但是如果類結構發生了非正常性的改變,例如修改了成員變量的類型結構,這種毀滅性的改變後,反序列化還是會失敗,因為無法從老版本的資料中還原一個新的類型結構的對象
注意:
1,靜态成員屬于類不屬于對象,是以不會參與序列化的過程
2,用transient關鍵字标記的成員變量不會參與序列化的過程
Parcelable接口
Parcelable 是android中提供的新的序列化方式,隻要實作這個接口,一個類的對象就可以實作序列化,并且可以通過Intent和Binder傳輸
執行個體如下:
public class User2 implements Parcelable {
public int age;
//體重
public int weight;
public String name;
public Book book;
public User2(){
}
public User2(Parcel in) {
//注意:這裡讀取字段的屬性要和寫入字段的順序一樣 age,weight,name,book
age=in.readInt();
weight=in.readInt();
name=in.readString();
//由于book是另一個序列化對象,是以它的反序列化的過程要傳遞目前上下文類加載器
book= in.readParcelable(Thread.currentThread().getContextClassLoader());
}
//studio會自動生成這裡
public static final Creator<User2> CREATOR = new Creator<User2>() {
@Override
public User2 createFromParcel(Parcel in) {
return new User2(in);
}
@Override
public User2[] newArray(int size) {
return new User2[size];
}
};
//studio會自動生成這裡
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(age);
dest.writeInt(weight);
dest.writeString(name);
dest.writeParcelable(book,0);
}
}
說明:
1,從Parcel in裡面讀取字段的順序一定要和writeToParcel字段的順序一樣(否則同一個類型的字段例如age和weight資料會搞混)
2,由于Book是另一個序列化對象,是以它的反序列化的過程要傳遞目前上下文類加載器
Parcelable接口和Serializable接口的比較
共同點:都能實作序列化并且都可用于Intent間的資料傳遞
不同點:Serializable是java中提供的接口,使用起來更加簡單,但是開銷很大,需要大量的IO操作,Parcelable是android中的序列化方式,是以更适用與android平台,缺點是使用起來稍微麻煩一點,優點是效率高
Binder:
直覺來講,Binder是android中的一個類,它實作了IBinder接口.從IPC的角度來講,Binder是Android中的一種跨程序通信方式,從AndroidFramework角度來講,Binder是ServiceManager連接配接各種Manager(ActivityNamager,WindowManger等等)的橋梁;從Android應用層來講,Binder是用戶端和服務端進行通信的媒介,當binderService的時候,服務端會傳回一個包含服務端業務調用的Binder對象,通過這個Binder對象,用戶端就可以擷取服務端提供的服務或者資料,這裡的服務包含普通的服務和基于AIDL的服務,普通的service服務不涉及程序間通信,主要是AIDL會涉及binder的核心
結尾:
下一篇會總結跨程序通信的幾種方式,盡情期待啦~^^