Android IPC多進(jìn)程介紹

注意:本篇文章是本人閱讀相關(guān)文章所寫下的總結(jié),方便以后查閱,所有內(nèi)容非原創(chuàng),侵權(quán)刪祟霍。

本篇文章內(nèi)容來(lái)自于:
Android開(kāi)發(fā)藝術(shù)探索

目錄

  1. 什么是IPC
  2. Android中的多進(jìn)程模式
    2.1 如何開(kāi)啟多進(jìn)程模式
    2.2 多進(jìn)程模式的壞影響(為什么會(huì)有各種跨進(jìn)程通信方式)
  3. IPC基礎(chǔ)概念
    3.1 Serializable接口
    3.2 Parcelable接口
    3.3 Binder接口

1. 什么是IPC

IPC(Inter-Process Communication),進(jìn)程間通信/跨進(jìn)程通信锉屈,指兩個(gè)進(jìn)程之間進(jìn)行數(shù)據(jù)交換苍狰。

進(jìn)程和線程的區(qū)別
線程:線程是CPU調(diào)度的最小單元办龄,同時(shí)線程是一種有限的系統(tǒng)資源。
進(jìn)程:進(jìn)程一般指一個(gè)執(zhí)行單元淋昭,在PC和移動(dòng)設(shè)備上指一個(gè)程序或者一個(gè)應(yīng)用俐填。
一個(gè)進(jìn)程可以包含多個(gè)線程,因此進(jìn)程和線程是包含和被包含的關(guān)系翔忽。

Android的進(jìn)程通信方式
通過(guò)Binder可以實(shí)現(xiàn)進(jìn)程間的通信英融。
通過(guò)Socket可以實(shí)現(xiàn)兩個(gè)終端之間的通信。

使用多進(jìn)程的場(chǎng)景(2種)
場(chǎng)景一:
一個(gè)應(yīng)用因?yàn)槟承┰蜃陨硇枰捎枚噙M(jìn)程模式來(lái)實(shí)現(xiàn)歇式。
比如有些模塊由于特殊原因需要運(yùn)行在單獨(dú)的進(jìn)程中驶悟。
比如為了加大一個(gè)應(yīng)用可使用的內(nèi)存所以需要通過(guò)多進(jìn)程來(lái)獲取多份內(nèi)存空間。Android為單個(gè)應(yīng)用使用的最大內(nèi)存做了限制材失,
場(chǎng)景二:
當(dāng)前應(yīng)用需要向其他應(yīng)用獲取數(shù)據(jù)痕鳍,因?yàn)槭?個(gè)應(yīng)用,則必須采用跨進(jìn)程的方式來(lái)獲取所需的數(shù)據(jù)龙巨;
甚至我們通過(guò)系統(tǒng)提供的ContentProvider去查詢數(shù)據(jù)的時(shí)候笼呆,也是一種進(jìn)程間通信,只不過(guò)通信細(xì)節(jié)被系統(tǒng)內(nèi)部屏蔽了旨别。

2. Android中的多進(jìn)程模式

2.1 如何開(kāi)啟多進(jìn)程模式

多進(jìn)程:一個(gè)應(yīng)用中存在多個(gè)進(jìn)程诗赌。

2.1.1 方法一:
通過(guò)四大組件指定android:process屬性,則可開(kāi)啟多進(jìn)程模式秸弛。

        <activity android:name=".DemoActivity" 
            android:process=":remote"/>
        <activity android:name=".HelloActivity"
            android:process="com.xl.haha">
  • DemoActivity啟動(dòng)時(shí)境肾,系統(tǒng)會(huì)為它創(chuàng)建一個(gè)新的進(jìn)程,進(jìn)程名為"com.xl.demo:remote"胆屿。(假設(shè)當(dāng)前包名為"com.xl.demo")
  • HelloActivity啟動(dòng)時(shí)奥喻,進(jìn)程名為"com.xl.haha"
  • 沒(méi)有指定process屬性的四大組件,則運(yùn)行在默認(rèn)進(jìn)程非迹,進(jìn)程名為包名

android:process=":remote"與"com.xl.haha"的區(qū)別
區(qū)別一:
":remote"的":"含義是指當(dāng)前的進(jìn)程名前面加上當(dāng)前的包名,是簡(jiǎn)寫环鲤。
"com.xl.haha"是完整的命名方式。
區(qū)別二:
":remote"是當(dāng)前應(yīng)用的私有進(jìn)程憎兽,其他應(yīng)用的組件不可以和它跑在同一個(gè)進(jìn)程中冷离。
"com.xl.haha"是全局進(jìn)程,其他應(yīng)用通過(guò)shareUID方式可以和它跑在同一個(gè)進(jìn)程中纯命。

Android系統(tǒng)會(huì)為每個(gè)應(yīng)用分配一個(gè)唯一的UID西剥,具有相同UID的應(yīng)用才能共享數(shù)據(jù)。
兩個(gè)應(yīng)用通過(guò)shareUID跑在同一個(gè)進(jìn)程中是有要求的亿汞,需要2個(gè)應(yīng)用有相同的shareUID并且簽名相同才可以瞭空。
此時(shí),他們可以互相訪問(wèn)彼此私有數(shù)據(jù)(data目錄、組件信息等)咆畏,不管他們是否跑在同一個(gè)進(jìn)程中南捂。

2.1.2 方法二:
通過(guò)JNI在native層去fork一個(gè)進(jìn)程。

2.2 多進(jìn)程模式的壞影響

多進(jìn)程帶來(lái)的影響:不同進(jìn)程中的四大組件不可以通過(guò)內(nèi)存來(lái)共享數(shù)據(jù)旧找。
因?yàn)閍ndroid為每個(gè)應(yīng)用/每個(gè)進(jìn)程分配一個(gè)獨(dú)立的虛擬機(jī)溺健,不同的虛擬機(jī)在內(nèi)存分配上有不同的地址空間,導(dǎo)致在不同的虛擬機(jī)訪問(wèn)同一個(gè)類的對(duì)象會(huì)產(chǎn)生多個(gè)副本钮蛛。

總而言之
使用多進(jìn)程會(huì)造成如下幾方面的問(wèn)題:
1.靜態(tài)成員和單例模式完全失效
2.線程同步機(jī)制完全失效
3.sharepreferences的可靠性下滑鞭缭。
4.application會(huì)多次重建。

為了解決這個(gè)問(wèn)題魏颓,雖然不能直接地共享內(nèi)存岭辣,但是系統(tǒng)提供很多跨進(jìn)程通信方法來(lái)實(shí)現(xiàn)數(shù)據(jù)交互。
跨進(jìn)程通信方式有:
通過(guò)Intent來(lái)傳遞數(shù)據(jù)
共享文件和sharedPreferences
基于Binder的Messenger和AIDL 單方面的客戶端向服務(wù)端推消息用AIDL
Socket 兩者互通用Socket

3. IPC基礎(chǔ)概念

Serializable和Parcelable可以完成對(duì)象的序列化過(guò)程琼开。

  • 當(dāng)我們需要用Intent或者Binder傳輸數(shù)據(jù)時(shí)需要使用Parcelable或Serializable
  • 我們需要將對(duì)象持久化到設(shè)備上或者通過(guò)網(wǎng)絡(luò)傳輸時(shí)易结,需要用Serializable完成對(duì)象持久化

3.1 Serializable接口

使用Serializable來(lái)序列化:
只需要這個(gè)類實(shí)現(xiàn)Serializable接口并聲明一個(gè)serialVersionUID(不是必須的)即可

//User類
public class User implements Serializable{
    private static final long serialVersionUID = 3983908423L;
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    ...
}

//實(shí)現(xiàn)序列化
        User user = new User("a", 1);
        File dir = Environment.getExternalStorageDirectory();
        File file = new File(dir, "haha.txt");
        //序列化  
        try {
            FileOutputStream fos = new FileOutputStream(file);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(user);
            oos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        //反序列化  
        try {
            FileInputStream fis = new FileInputStream(file);
            ObjectInputStream ois = new ObjectInputStream(fis);
            User user1 = (User) ois.readObject();
            Log.d("xl", user1.toString());
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

關(guān)于serialVersionUID
serialVersionUID用于輔助序列化和反序列化過(guò)程的。
序列化后的數(shù)據(jù)中的serialVersionUID只有和當(dāng)前類的serialVersionUID相同才能夠正常的反序列化柜候。

serialVersionUID的詳細(xì)工作機(jī)制:
序列化的時(shí)候系統(tǒng)會(huì)把當(dāng)前類的serialVersionUID寫入序列化的文件中搞动,當(dāng)反序列化的時(shí)候系統(tǒng)會(huì)去檢測(cè)文件中的serialVersionUID,看它是否和當(dāng)前類的serialVersionUID一致渣刷。
如果一致則說(shuō)明序列化的類的版本和當(dāng)前類的版本是相同的鹦肿,這個(gè)時(shí)候可以成功反序列化;否則則說(shuō)明當(dāng)前類和序列化的類相比發(fā)生了某些變換(比如成員變量的數(shù)量辅柴、類型發(fā)生變化)箩溃,則無(wú)法正常反序列化。
建議手動(dòng)賦值碌嘀,在很大程度上避免反序列化的失敗涣旨。

3.2 Parcelable接口

只需要實(shí)現(xiàn)這個(gè)接口即可。

public class User implements Parcelable{
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    protected User(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }

    //反序列化
    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];
        }
    };

    //內(nèi)容描述
    @Override
    public int describeContents() {
        return 0;
    }

    //序列化
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
    }
}

關(guān)于Parcel
Parcel內(nèi)部包裝了可序列化的數(shù)據(jù)股冗,

選擇Parcelable還是Serializable霹陡?
Serializable是Java中的序列化接口,使用簡(jiǎn)單但開(kāi)銷大止状,序列化和反序列化需要大量IO操作烹棉。
Parcelable是Android中的序列化方式,更適合用于Android怯疤,只是操作麻煩浆洗,但效率高,是Android推薦的序列化方式集峦。
因此首選Parcelable伏社。
Parcelable主要用在內(nèi)存序列化上抠刺。
將對(duì)象序列化到存儲(chǔ)設(shè)備或者網(wǎng)絡(luò)傳輸用Serializable

3.3 Binder接口

Binder是Android的一個(gè)類,實(shí)現(xiàn)了IBinder接口洛口。

public class Binder implements IBinder {
3.3.1 什么是Binder
  • 從IPC角度來(lái)說(shuō)矫付,Binder是Android中的一個(gè)跨進(jìn)程通信方式
  • 可以理解為一種虛擬的物理設(shè)備凯沪,設(shè)備驅(qū)動(dòng)是/dev/binder第焰,該通信方式linux中沒(méi)有。
  • 從Android Framework角度來(lái)說(shuō)妨马,Binder是ServiceManager連接各種Manager(ActivityManager等)和相應(yīng)ManagerService的橋梁挺举。
  • 從Android應(yīng)用層來(lái)說(shuō),Binder是客戶端和服務(wù)端進(jìn)行通信的媒介烘跺,當(dāng)bindService時(shí)湘纵,服務(wù)端返回一個(gè)包含服務(wù)端業(yè)務(wù)調(diào)用的Binder對(duì)象,通過(guò)這個(gè)Binder對(duì)象滤淳,客戶端可以獲取服務(wù)端提供的服務(wù)或者數(shù)據(jù)梧喷,這里的服務(wù)包括普通服務(wù)和基于AIDL的服務(wù)。

Binder主要用于Service中脖咐,包括AIDL和Messenger铺敌。
其中普通Service中的Binder不涉及進(jìn)程間通信。
Messenger的底層其實(shí)是AIDL屁擅。

3.3.2 Binder的使用以及工作機(jī)制

ALDL示例(Binder的使用):
Android:如何創(chuàng)建一個(gè)AIDL

完成創(chuàng)建后偿凭,SDK會(huì)自動(dòng)生成AIDL所對(duì)應(yīng)的Binder類。
在build/generated/source/aidl/你的 flavor/ 下派歌。


Binder的工作機(jī)制

使用時(shí)弯囊,當(dāng)調(diào)用相應(yīng)的接口方法getBookList(),
則會(huì)先調(diào)用Stub的getBookList()方法胶果,
該方法首先創(chuàng)建該方法的輸入型和輸出型Parcel對(duì)象_data匾嘱、_reply 和返回值對(duì)象,
將方法參數(shù)寫入_data早抠,再調(diào)用transact方法來(lái)發(fā)起RPC請(qǐng)求霎烙,同時(shí)當(dāng)前線程掛起。
然后服務(wù)端的onTransact方法會(huì)被調(diào)用贝或。
直到RPC過(guò)程返回后吼过,當(dāng)前線程繼續(xù)執(zhí)行,并從_reply中取出RPC過(guò)程返回結(jié)果咪奖。
當(dāng)服務(wù)端的onTransact方法被調(diào)用
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
服務(wù)端通過(guò)code來(lái)確定所請(qǐng)求的目標(biāo)方法盗忱。從data中取出目標(biāo)方法需要的參數(shù),然后執(zhí)行目標(biāo)方法羊赵。
目標(biāo)方法執(zhí)行完趟佃,則往reply中寫入返回值扇谣。

3.3.3 Binder的重連機(jī)制

Binder運(yùn)行在服務(wù)端闲昭,如果服務(wù)端進(jìn)程由于某種原因異常停止罐寨,這個(gè)時(shí)候我們服務(wù)端的Binder連接斷裂(Binder死亡),會(huì)導(dǎo)致我們的遠(yuǎn)程調(diào)用失敗序矩。

Binder的2個(gè)很重要的方法linkToDeath和unlinkToDeath
通過(guò)linkToDeath可以給Binder設(shè)置一個(gè)死亡代理簸淀,當(dāng)Binder死亡時(shí)劲绪,我們會(huì)收到通知,可以重新發(fā)起請(qǐng)求從而恢復(fù)連接祷安。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子米间,更是在濱河造成了極大的恐慌,老刑警劉巖雕薪,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異凶掰,居然都是意外死亡勺拣,警方通過(guò)查閱死者的電腦和手機(jī)药有,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門苇经,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)奠旺,“玉大人装诡,你說(shuō)我怎么就攤上這事∮娌” “怎么了鲜侥?”我有些...
    開(kāi)封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)篡撵。 經(jīng)常有香客問(wèn)我,道長(zhǎng)容贝,這世上最難降的妖魔是什么斤富? 我笑而不...
    開(kāi)封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任膏潮,我火速辦了婚禮,結(jié)果婚禮上满力,老公的妹妹穿的比我還像新娘焕参。我一直安慰自己轻纪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布叠纷。 她就那樣靜靜地躺著刻帚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪涩嚣。 梳的紋絲不亂的頭發(fā)上崇众,一...
    開(kāi)封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音航厚,去河邊找鬼顷歌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛幔睬,可吹牛的內(nèi)容都是我干的眯漩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼溪窒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼坤塞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起澈蚌,我...
    開(kāi)封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎灼狰,沒(méi)想到半個(gè)月后宛瞄,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡交胚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年份汗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝴簇。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡杯活,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出熬词,到底是詐尸還是另有隱情旁钧,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布互拾,位于F島的核電站歪今,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏颜矿。R本人自食惡果不足惜寄猩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望骑疆。 院中可真熱鬧田篇,春花似錦替废、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至彬呻,卻和暖如春衣陶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背闸氮。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工剪况, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蒲跨。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓译断,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親或悲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子孙咪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android跨進(jìn)程通信IPC整體內(nèi)容如下 1、Android跨進(jìn)程通信IPC之1——Linux基礎(chǔ)2巡语、Andro...
    隔壁老李頭閱讀 11,850評(píng)論 6 38
  • 一翎蹈、IPC簡(jiǎn)介 (1)IPC是Inter-Process Communication的縮寫,含義為進(jìn)程間通信或者跨...
    遙遙的遠(yuǎn)方閱讀 7,217評(píng)論 0 3
  • 一男公、Android IPC簡(jiǎn)介 IPC是Inter-Process Communication的縮寫荤堪,含義就是進(jìn)程...
    SeanMa閱讀 1,819評(píng)論 0 8
  • 多進(jìn)程概念和多進(jìn)程開(kāi)發(fā)模式中常見(jiàn)問(wèn)題 Android序列化機(jī)制和Binder 詳細(xì)介紹Bundle、文件共享枢赔、AI...
    Danny_yy閱讀 754評(píng)論 0 1
  • 朋友的黑貓警長(zhǎng)和呆呆貍 黑貓警長(zhǎng)的品種是中華田園貓澄阳,但是由于外貌的特定,又名烏云踏雪踏拜。
    潘達(dá)說(shuō)閱讀 149評(píng)論 0 0