Android: IPC 方式學習筆記

IPC 簡介


IPC 是 Inter-Process Communication 的縮寫,含義為進程間通信或跨進程通信,是指兩個進程之間進行數據交換的過程。

IPC 的場景

  • 一個應用由于自身需要,采用多進程方式實現。例如:某個模塊需要運行在單獨的進程中。
  • 兩個應用交換數據。

應用使用多進程會導致的問題

  • 靜態成員和單例模式失效
    Android 為每個進程分配獨立的虛擬機,不同的虛擬機分配了不同的內存空間,一個進程中對靜態變量的修改只對本進程有效。
  • 線程同步機制失效
    不論鎖對象還是全局類都無法保證線程同步,因為在不同進程中鎖的不是同一個對象。
  • SharedPreferences 的可靠性降低
    兩個進程并發寫 SharedPreferences ,可能會發生數據丟失的情況。
  • Application 會多次創建
    每個進程運行在獨立的虛擬機上,會創建獨立的 Application 實例。

IPC 方式


1.Bundle

四大組件之三 Activity、Service 和 BroadcastReceiver 均支持在 Intent 中傳遞 Bundle 數據。

當我們需要向其他進程傳輸數據時,可以通過 Intent 將需要傳遞的數據傳遞給目標進程的組件。

要求:需要傳遞的數據能夠被序列化,例如基本類型、實現了 Parcelable 或 Serializable 接口的類的實例、Android 支持的特殊對象。

Bundle 不支持的類型無法通過這種方式進行進程間通信。

2. 文件共享

兩個進程通過讀寫同一個文件來交換數據。

除了可以交換文本信息外,也可以傳遞序列化的對象。

適用場景:對數據同步要求不高的進程間通信,需要妥善處理并發讀寫問題。

SharedPreferences 是使用 XML 文件來存儲鍵值對的,但是 Android 系統會在內存中對它進行緩存,在多進程模式下,系統對它的讀寫就不再可靠。當面對高并發的讀寫訪問時,SharedPreferences 很可能會丟失數據。所以,不建議在進程間通信中使用 SharedPreferences,可以考慮使用 MMKV。

MMKV for Android 多進程訪問支持的設計與實現

3. Messenger

Messenger 信使,它可以在不同進程間傳遞 Message 對象。在 Message 對象中放入需要傳遞的數據,就可以輕松地實現進程間傳遞數據的目標。

Messenger 是一種輕量級的 IPC 方案,底層實現是 AIDL 。

Message 中能使用的載體有 what(int)、arg1(int)、arg2(int)、Bundle 和 replyTo(Messenger) 。

Messenger 的使用
  1. 服務端進程
  • 創建一個 Service 來處理客戶端的連接請求
  • 創建一個 Handler,并通過它來創建一個 Messenger 對象
  • 在 Service 的 onBind 中返回 Messenger 對象底層的 IBinder
  1. 客戶端進程
  • 綁定服務端的 Service,用服務端返回的 IBinder 對象創建一個 Messenger
  • 用 Messenger 向服務端發送消息,消息的類型為 Message

通過以上操作,就可以完成客戶端向服務端的單向通信了。如需支持服務端響應客戶端:

  1. 客戶端進程
  • 創建一個 Handler,并通過它創建一個新的 Messenger 對象
  • 將新創建的 Messenger 對象通過 Message 的 replyTo 參數傳遞給服務端進程
  1. 服務端進程
  • 取出客戶端通過 replyTo 參數的傳遞過來的 Messenger 對象
  • 使用 Messenger 對象回應客戶端
Messenger的工作原理.png

4. AIDL

使用 AIDL 進行進程間通信的流程
  1. 服務端
  • 創建一個 Service,用來監聽客戶端的連接請求
  • 創建一個 AIDL 文件,用來聲明暴露給客戶端的接口
  • 在 Service 中實現 AIDL 文件中聲明的接口
  1. 客戶端
  • 綁定服務端的 Service
  • 將服務端返回的 Binder 對象轉成 AIDL 接口所屬的類型
  • 調用 AIDL 中的方法

AIDL 支持的數據類型

  • 基本數據類型
  • String 和 CharSequence
  • ArrayList,集合中的每個元素必須被 AIDL 支持
  • HashMap,集合中的每個元素必須被 AIDL 支持,包括 key 和 value
  • Parcelable:所有實現了 Parcelable 接口的類
  • AIDL:所有的 AIDL 接口

5. ContentProvider

ContentProvider 是 Android 提供的不同應用間數據共享的方式,底層實現是 Binder。

Android 系統預置了許多 ContentProvider,比如通訊錄信息、日程表信息等,要跨進程訪問這些信息,只需要通過 ContentResolver 的 query()、update()、insert() 和 delete() 方法即可。

ContentProvider 主要以表格的形式組織數據,和數據庫相似。它還支持文件文件數據,例如圖片、視頻等。Android 提供的 MediaStore 就是文件類型的 ContentProvider。

雖然 ContentProvider 的底層數據看起來很像一個 SQLite 數據庫,但是它對數據的存儲方法并沒有任何要求,我們既可以使用 SQLite 數據庫,也可以使用普通的文件,甚至可以采用內存中的一個對象來進行數據的存儲。

自定義 ContentProvider
  • 繼承 ContentProvider 類,實現 6 個抽象方法:onCreate()、query()、update()、insert()、delete() 和 getType() 。
  • 建立數據存儲系統,比較常用的使用 SQLite 數據庫。
  • 注冊 ContentProvider,在 AndroidManifest 文件中聲明。
ContentProvider 的抽象方法
  • onCreate() : ContentProvider 的初始化。
  • getType() : 返回一個 Uri 請求所對應的 MIME 類型。
  • query()、update()、insert() 和 delete(): 數據的增刪改查。
  • 6 個方法均運行在 ContentProvider 的進程中,onCreate() 由系統回調并運行在主線程里,其他 5 個方法均由外界回調并運行在 Binder 線程池中。

6. Socket

Socket,套接字,是網絡通信中的概念。分為流式套接字和用戶數據報套接字兩種,分別對應網絡的傳輸控制層中的 TCP 和 UDP。

通過 Socket 不僅能實現進程間的通信,還可以實現設備間的通信,前提是通信的設備的 IP 地址互相可見。

IPC 方式比較

名稱 優點 缺點 適用場景
Bundle 簡單易用 只能傳輸 Bundle 支持的數據類型 四大組件間的進程間通信
文件共享 簡單易用 不適合高并發場景,不支持進程間的即時通信 無并發需求,交換簡單的數據,對實時性要求不高
AIDL 支持一對多并發通信,支持實時通信 使用比較復雜,需要處理好線程同步 一對多通信,有 RPC 需求
Messenger 支持一對多串行通信,支持實時通信 只能傳輸 Bundle 支持的數據類型,不能很好地處理高并發情形,不支持 RPC 低并發的一對多通信,無 RPC 需求,或者有不需要返回結果的 RPC 需求
ContentProvider 支持一對多并發數據共享,可通過 Call 方法擴展其他操作 主要提供數據源的 CRUD 操作 一對多的進程間的數據共享
Socket 支持一對多并發實時通信,可以通過網絡傳輸字節流 使用比較復雜,不支持直接 RPC 網絡數據交換

測試設備參數

  • 型號:vivo Y66L
  • 操作系統:Funtouch OS 3.0(Android 6.0.1)

參考資料

任玉剛.Android 開發藝術探索[M].電子工業出版社:北京,2015:35-121.

示例代碼

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容