Android進(jìn)程通信

參考:https://blog.csdn.net/hzw2017/article/details/81275438

一益兄、進(jìn)程

Android中進(jìn)程分為5種:

1 Foreground process 前端進(jìn)程

目前顯示在屏幕上和用戶交互的進(jìn)程蠢正。
比如:
頂層可交互的Activity(已執(zhí)行onResume)嗅虏;
有個(gè)Service秘蛔,并綁定到跟用戶正在交互的Activity雳锋;
在Service里調(diào)用了startForeground函數(shù)饼丘;
正在執(zhí)行onReceive的BroadcastReceiver笼恰。

2 Visible process 可見進(jìn)程

沒有任何前臺組件冤荆,但仍能影響用戶在屏幕上看到東西朴则。
比如:
如果一個(gè)Activity在一個(gè)對話框運(yùn)行之后仍然是可視的;
輸入法彈出時(shí)钓简。

3 Service process 服務(wù)進(jìn)程

服務(wù)進(jìn)程不會(huì)直接為用戶所見乌妒。
比如:
在后臺播放mp3或者下載東西。

4 Background process 后臺進(jìn)程

比如:
Activity執(zhí)行了onStop外邓。

5 Empty process 空進(jìn)程
優(yōu)先級層次
Android進(jìn)程層次.png

RPC 和 IPC

RPC:Remote Procedure Call撤蚊,即遠(yuǎn)程過程調(diào)用,它是一種通過網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請求服務(wù)损话,在不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議下侦啸,即可獲取計(jì)算機(jī)進(jìn)程中的數(shù)據(jù)槽唾。RPC使得開發(fā)包括網(wǎng)絡(luò)分布式多程序在內(nèi)的應(yīng)用程序更加容易。
RPC在OSI網(wǎng)絡(luò)通信7層模型中光涂,位于傳輸層與應(yīng)用層之間庞萍,即位于會(huì)話層。

RPC可以說客戶端調(diào)用服務(wù)端的接口的過程忘闻,是面向接口的編程钝计。

RPC與IPC的關(guān)系:
Android 利用遠(yuǎn)程過程調(diào)用 (RPC) 提供了一種進(jìn)程間通信 (IPC) 機(jī)制,通過這種機(jī)制齐佳,由 Activity 或其他應(yīng)用組件調(diào)用的方法將(在其他進(jìn)程中)遠(yuǎn)程執(zhí)行私恬,而所有結(jié)果將返回給調(diào)用方。
這就要求把方法調(diào)用及其數(shù)據(jù)分解至操作系統(tǒng)可以識別的程度重虑,并將其從本地進(jìn)程和地址空間傳輸至遠(yuǎn)程進(jìn)程和地址空間践付,然后在遠(yuǎn)程進(jìn)程中重新組裝并執(zhí)行該調(diào)用。然后缺厉,返回值將沿相反方向傳輸回來永高。Android 提供了執(zhí)行這些 IPC 事務(wù)所需的全部代碼,因此您只需集中精力定義和實(shí)現(xiàn) RPC 編程接口即可提针。
要執(zhí)行 IPC命爬,必須使用 bindService() 將應(yīng)用綁定到服務(wù)上。

也就是說辐脖,RPC在的Android具體體現(xiàn)饲宛,是依賴 bindService()的方式,在onBind方法將服務(wù)端的計(jì)算結(jié)果返回給客戶端(Activity等組件)的過程嗜价。

IPC:Inter-Process Communication艇抠,即進(jìn)程間通信,是指進(jìn)程間數(shù)據(jù)交互的過程久锥。

Android底層是基于Linux家淤,而Linux基于安全考慮,是不允許兩個(gè)進(jìn)程間直接操作對方的數(shù)據(jù)瑟由,這就是進(jìn)程隔離絮重。

在Linux系統(tǒng)中,虛擬內(nèi)存機(jī)制為每個(gè)進(jìn)程分配了線性連續(xù)的內(nèi)存空間歹苦,操作系統(tǒng)將這種虛擬內(nèi)存空間映射到物理內(nèi)存空間青伤,每個(gè)進(jìn)程有自己的虛擬內(nèi)存空間,進(jìn)而不能操作其他進(jìn)程的內(nèi)存空間殴瘦,每個(gè)進(jìn)程只能操作自己的虛擬內(nèi)存空間狠角,只有操作系統(tǒng)才有權(quán)限操作物理內(nèi)存空間。進(jìn)程隔離保證了每個(gè)進(jìn)程的內(nèi)存安全蚪腋,但是在大多數(shù)情形下擎厢,不同進(jìn)程間的數(shù)據(jù)通訊是不可避免的究流,因此操作系統(tǒng)必須提供跨進(jìn)程通信機(jī)制。

Android應(yīng)用中使用多進(jìn)程:

  • 在AndroidManifest.xml中聲明組件時(shí)动遭,用android:process屬性來指定進(jìn)程芬探。

  • 不指定process屬性,則默認(rèn)運(yùn)行在主進(jìn)程中厘惦,主進(jìn)程名字為包名偷仿。

  • android:process = package:remote,將運(yùn)行在package:remote進(jìn)程中宵蕉,屬于全局進(jìn)程酝静,其他具有相同shareUID與簽名的APP可以跑在這個(gè)進(jìn)程中。

  • android:process = :remote 羡玛,將運(yùn)行在默認(rèn)包名:remote進(jìn)程中别智,而且是APP的私有進(jìn)程,不允許其他APP的組件來訪問稼稿。

多進(jìn)程引發(fā)的問題

  • 靜態(tài)成員和單例失效:每個(gè)進(jìn)程保持各自的靜態(tài)成員和單例薄榛,相互獨(dú)立。

  • 線程同步機(jī)制失效:每個(gè)進(jìn)程有自己的線程鎖让歼。

  • SharedPreferences可靠性下降:不支持并發(fā)寫敞恋,會(huì)出現(xiàn)臟數(shù)據(jù)。

  • Application多次創(chuàng)建:不同進(jìn)程跑在不同虛擬機(jī)谋右,每個(gè)虛擬機(jī)啟動(dòng)會(huì)創(chuàng)建自己的Application硬猫,自定義Application時(shí)生命周期會(huì)混亂。

綜上改执,不同進(jìn)程擁有各自獨(dú)立的虛擬機(jī)啸蜜、Application、內(nèi)存空間辈挂,不同進(jìn)程訪問同一個(gè)類的對象會(huì)有不同的副本盔性,由此引發(fā)一系列問題。


二呢岗、進(jìn)程間通信

雖然Android是基于Linux,但并不能繼承Linux中的進(jìn)程通信的方式蛹尝,Android有著自己進(jìn)程間通信方式后豫。

1 Bundle (四大組件間)

可傳遞基本類型String突那、實(shí)現(xiàn)了Serializable或Parcelable接口的數(shù)據(jù)結(jié)構(gòu)挫酿。

Serializable是Java的序列化方法,Parcelable是Android的序列化方法愕难。前者代碼量少(僅一句)早龟,但I(xiàn)/O開銷較大惫霸,一般用于輸出到磁盤或網(wǎng)卡;后者實(shí)現(xiàn)代碼多葱弟,效率高壹店,一般用戶內(nèi)存間序列化和反序列化傳輸。

詳情請移步:

2 文件共享

對同一個(gè)文件先后寫讀芝加,從而實(shí)現(xiàn)傳輸硅卢,Linux機(jī)制下,可以對文件并發(fā)寫藏杖,所以要注意同步将塑。順便一提,Windows下不支持并發(fā)讀或?qū)憽?/p>

3 Messenger(基于Binder)

Messenger是基于AIDL實(shí)現(xiàn)的蝌麸,通過Message對象進(jìn)行跨進(jìn)程通信点寥,類似于Handler發(fā)送消息實(shí)現(xiàn)線程間通信。服務(wù)端(被動(dòng)方)提供一個(gè)Service來處理客戶端(主動(dòng)方)連接来吩,維護(hù)一個(gè)Handler來創(chuàng)建Messenger敢辩,在onBind時(shí)返回Messenger的binder。

雙方用Messenger來發(fā)送數(shù)據(jù)误褪,用Handler來處理數(shù)據(jù)责鳍。Messenger處理數(shù)據(jù)依靠Handler,所以是串行的兽间,也就是說历葛,Handler接到多個(gè)message時(shí),就要排隊(duì)依次處理嘀略。

此外恤溶,還支持記錄客戶端對象的Messenger,然后可以實(shí)現(xiàn)一對多的通信帜羊;甚至作為一個(gè)轉(zhuǎn)接處咒程,任意兩個(gè)進(jìn)程都能通過服務(wù)端進(jìn)行通信。

與 AIDL 比較:
  • 當(dāng)需要執(zhí)行 IPC 時(shí)讼育,為接口使用 Messenger 要比使用 AIDL 實(shí)現(xiàn)更加簡單帐姻,因?yàn)?Messenger 會(huì)將所有服務(wù)調(diào)用排入隊(duì)列,而純粹的 AIDL 接口會(huì)同時(shí)向服務(wù)發(fā)送多個(gè)請求奶段,服務(wù)隨后必須應(yīng)對多線程處理饥瓷。
  • 對于大多數(shù)應(yīng)用,服務(wù)不需要執(zhí)行多線程處理痹籍,因此使用 Messenger 可讓服務(wù)一次處理一個(gè)調(diào)用呢铆。如果服務(wù)必須執(zhí)行多線程處理,則應(yīng)使用 AIDL 來定義接口蹲缠。
使用步驟
服務(wù)端:
  1. 創(chuàng)建一個(gè)Handler對象棺克,并實(shí)現(xiàn)handleMessage方法悠垛,用于接收和處理來自客戶端的消息。
  2. 創(chuàng)建一個(gè)Messenger作為送信人娜谊,封裝Handler确买。
  3. 用Messenger的getBinder()方法獲取一個(gè)IBinder對象,通過onBind返回給客戶端因俐。
客戶端:
  1. 在Activity中綁定服務(wù)拇惋。
  2. 創(chuàng)建ServiceConnection并在其中使用 IBinder 將 Messenger實(shí)例化。
  3. 使用Messenger向服務(wù)端發(fā)送消息抹剩。
  4. 解綁服務(wù)撑帖。
  5. 服務(wù)端中在 handleMessage() 方法中接收每個(gè) Message。

以上實(shí)現(xiàn)的僅僅是單向通信澳眷,即客戶端給服務(wù)端發(fā)送消息胡嘿,如果需要服務(wù)端給客戶端發(fā)送消息,需要接著上面的步驟繼續(xù):

  1. 在客戶端中創(chuàng)建一個(gè)Handler對象钳踊,用于處理服務(wù)端發(fā)過來的消息衷敌。
  2. 創(chuàng)建一個(gè)客戶端自己的Messenger對象,并封裝Handler拓瞪。
  3. 將客戶端的Messenger對象賦給待發(fā)送的Message對象的replyTo字段缴罗。
  4. 在服務(wù)端的Handler處理Message時(shí)將客戶端的Messenger解析出來,并使用客戶端的Messenger對象給客戶端發(fā)送消息祭埂。

其實(shí)Messenger底層也是AIDL面氓。客戶端和服務(wù)端通訊蛆橡,就是普通的AIDL舌界,客戶端實(shí)例化Stub之后,通過Stub的send方法把消息發(fā)到服務(wù)端泰演。服務(wù)端和客戶端通訊:服務(wù)端通過解析Message的replyTo呻拌,獲得客戶端的Stub,然后通過send方法發(fā)送到客戶端睦焕。

注意:Service在聲明時(shí)必須對外開放藐握,即android:exported="true"

4 AIDL(基于Binder)

Google Doc:https://developer.android.google.cn/guide/components/aidl

AIDL:Android Interface Definition Language垃喊,即Android接口定義語言猾普。可以利用它定義客戶端與服務(wù)使用進(jìn)程間通信 (IPC) 進(jìn)行相互通信時(shí)都認(rèn)可的編程接口缔御。

:只有允許不同應(yīng)用的客戶端用 IPC 方式訪問服務(wù),并且想要在服務(wù)中處理多線程時(shí)妇蛀,才有必要使用 AIDL耕突。 如果不需要執(zhí)行跨越不同應(yīng)用的并發(fā) IPC笤成,就應(yīng)該通過實(shí)現(xiàn)一個(gè) Binder創(chuàng)建接口;或者眷茁,如果想執(zhí)行 IPC炕泳,但根本不需要處理多線程,則使用 Messenger 類來實(shí)現(xiàn)接口上祈。無論如何培遵,在實(shí)現(xiàn) AIDL 之前,需要理解綁定服務(wù)登刺。

從某種意義上說AIDL其實(shí)是一個(gè)模板籽腕,因?yàn)樵谑褂眠^程中,實(shí)際起作用的并不是AIDL文件纸俭,而是據(jù)此而生成的一個(gè)IInterface的實(shí)例代碼皇耗,AIDL其實(shí)是為了避免我們重復(fù)編寫代碼而出現(xiàn)的一個(gè)模板。

通過編寫aidl文件來設(shè)計(jì)想要暴露的接口揍很,編譯后會(huì)自動(dòng)生成相應(yīng)的java文件郎楼,服務(wù)器將接口的具體實(shí)現(xiàn)寫在Stub中,用IBinder對象傳遞給客戶端窒悔,客戶端bindService的時(shí)候呜袁,用asInterface的形式將IBinder還原成接口,再調(diào)用其中的方法简珠。

AIDL支持的數(shù)據(jù)類型
  • 基本數(shù)據(jù)類型(int阶界、long、char北救、boolean荐操、double、byte珍策、short托启、float)
  • String 和 CharSequence
  • List、Map集合:
    List/Map中的所有元素都必須是以上列表中支持的數(shù)據(jù)類型攘宙、其他 AIDL 生成的接口或聲明的可打包類型屯耸。可選擇將 List/Map 用作“通用”類(例如蹭劈,List<String>疗绣、Map<String,Integer>)。
    另一端實(shí)際接收的具體類始終是 ArrayList/HashMap铺韧,但生成的方法使用的是 List/Map 接口多矮。
  • 實(shí)現(xiàn)了 Parcelable 接口的對象
  • AIDL本身接口也可以在AIDL文件使用

AIDL使用步驟

  1. 創(chuàng)建 .aidl 文件
    此文件定義帶有方法簽名的編程接口。
  2. 實(shí)現(xiàn)接口
    Android SDK 工具基于您的 .aidl 文件,使用 Java 編程語言生成一個(gè)接口塔逃。此接口具有一個(gè)名為 Stub 的內(nèi)部抽象類讯壶,用于擴(kuò)展 Binder 類并實(shí)現(xiàn) AIDL 接口中的方法。您必須擴(kuò)展 Stub 類并實(shí)現(xiàn)方法湾盗。
  3. 向客戶端公開該接口
    實(shí)現(xiàn) Service 并重寫 onBind() 以返回 Stub 類的實(shí)現(xiàn)伏蚊。

AIDL詳情請移步:Android進(jìn)程通信-AIDL

5 ContentProvider(基于Binder)

Google Doc: https://developer.android.google.cn/guide/topics/providers/content-providers

系統(tǒng)四大組件之一,底層也是基于Binder實(shí)現(xiàn)的格粪,是Android跨進(jìn)程實(shí)現(xiàn)數(shù)據(jù)共享的標(biāo)準(zhǔn)方式躏吊。
ContentProvider主要用于在不同的應(yīng)用程序間實(shí)現(xiàn)數(shù)據(jù)共享,允許一個(gè)程序訪問另外一個(gè)程序中的數(shù)據(jù)帐萎,還能保證數(shù)據(jù)訪問的安全性比伏,可以說天生就是為進(jìn)程通信而生的。

  • 自己實(shí)現(xiàn)一個(gè)ContentProvider需要實(shí)現(xiàn)6個(gè)方法吓肋,其中onCreate是主線程中回調(diào)的凳怨,其他方法是運(yùn)行在Binder之中的。
  • 自定義的ContentProvider注冊時(shí)要提供authorities屬性是鬼,應(yīng)用需要訪問的時(shí)候?qū)傩园b成Uri.parse("content://authorities")肤舞。
  • 還可以設(shè)置permissionreadPermission均蜜、writePermission來設(shè)置權(quán)限李剖。
  • ContentProvider有query,delete囤耳,insert等方法篙顺,看起來貌似是一個(gè)數(shù)據(jù)庫管理類,但其實(shí)可以用文件充择、內(nèi)存數(shù)據(jù)等等一切來充當(dāng)數(shù)據(jù)源德玫,query返回的是一個(gè)Cursor,可以自定義繼承AbstractCursor的類來實(shí)現(xiàn)椎麦。

這里不再贅述宰僧,詳情可參考:https://blog.csdn.net/hzw2017/article/details/81123791

6 Socket(網(wǎng)絡(luò))

請移步:網(wǎng)絡(luò)通信-Socket

6種IPC方式對比

IPC方式對比.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市观挎,隨后出現(xiàn)的幾起案子琴儿,更是在濱河造成了極大的恐慌,老刑警劉巖嘁捷,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件造成,死亡現(xiàn)場離奇詭異,居然都是意外死亡雄嚣,警方通過查閱死者的電腦和手機(jī)晒屎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鼓鲁,你說我怎么就攤上這事履肃。” “怎么了坐桩?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長封锉。 經(jīng)常有香客問我绵跷,道長,這世上最難降的妖魔是什么成福? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任碾局,我火速辦了婚禮,結(jié)果婚禮上奴艾,老公的妹妹穿的比我還像新娘净当。我一直安慰自己,他們只是感情好蕴潦,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布像啼。 她就那樣靜靜地躺著,像睡著了一般潭苞。 火紅的嫁衣襯著肌膚如雪忽冻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天此疹,我揣著相機(jī)與錄音僧诚,去河邊找鬼。 笑死蝗碎,一個(gè)胖子當(dāng)著我的面吹牛湖笨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蹦骑,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼慈省,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了脊串?” 一聲冷哼從身側(cè)響起辫呻,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎琼锋,沒想到半個(gè)月后放闺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缕坎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年怖侦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡匾寝,死狀恐怖搬葬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情艳悔,我是刑警寧澤急凰,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站猜年,受9級特大地震影響抡锈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乔外,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一床三、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧杨幼,春花似錦撇簿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至欲逃,卻和暖如春莲组,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背暖夭。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工锹杈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人迈着。 一個(gè)月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓竭望,卻偏偏與公主長得像,于是被迫代替她去往敵國和親裕菠。 傳聞我的和親對象是個(gè)殘疾皇子咬清,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

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