Android 多進程通訊之幾個基本問題

Android多進程系列

開啓多進程的方法

Android 中使用多進程只有一種方法,那就是給四大組件(Activity、Service、Receiver、ContentProvider)在AndroidMenifest中指定android:process屬性android

<service
    android:name="com.xxq2dream.service.BookManagerService"
    android:process=":remote" />
複製代碼
  • 經過如上的設置,BookManagerService就運行在獨立的進程下,進程名爲:包名:remote,好比:com.xxq2dream.android_ipc:remote
  • 上面的設置方法表示remote進程是當前應用的私有進程,其餘應用的組件不能夠和它跑在同一個進程中
  • android:process屬性的設置還有另外一種方式com.xxq2dream.android_ipc.remote,這種方式的進程是全局進程,其餘應用經過ShareUID方式能夠和它跑在同一個進程中。
  • 通常咱們在應用中用的比較多的是第一種,也便是應用的私有進程

開啓多進程模式後的問題

Android爲每一個進程都分配一個獨立的虛擬機,不一樣的虛擬機在內存分配上有不一樣的地址空間,這就致使了不一樣的虛擬機中訪問同一個類的對象會產生多個副本。一個應用間的多進程能夠理解爲就至關於2個不一樣的應用採用了SharedUID的模式。緩存

  • 全部運行在不一樣的進程中的四大組件,只要它們之間須要經過內存來共享數據,都會共享失敗
  • 靜態成員和單例模式徹底失效(不一樣進程的內存區域都不同了)
  • 線程同步機制徹底失效(不一樣的進程鎖的都不是同一個對象)
  • Application會屢次建立
  • SharedPreferce的可靠性降低(SharedPreferce底層是讀寫xml文件實現的,系統對它的讀寫有必定的緩存策略,在內存中會有一份SharedPreferce文件的緩存,因此多個進程併發寫操做可能致使數據丟失)

多進程通訊的實現方式

使用Bundle
  • 四大組件中的三大組件(Activity、Service、Receiver)都支持在Intent中傳遞Bundle數據
  • Bundle中的數據除了基本類型,其餘的都須要可序列化
  • 適用於從一個進程啓動另外一個進程,好比在一個進程中啓動另外一個進程中的Activity、Service、Receiver,與此同時傳遞數據的狀況
使用文件共享
  • 2個進程經過讀寫同一個文件來交換數據
  • 固然要把數據寫入文件,必然要求數據能夠序列化和反序列化
  • 文件共享對文件格式沒有要求,只要讀寫雙方約定好數據格式
  • 文件共享的方式存在併發讀寫的問題,適合對數據同步要求不高的進程間通訊,而且要妥善處理併發讀寫的問題
使用Messager
  • 使用Messager來傳遞Message,Message中能使用的字段只有what、arg一、arg二、Bundle和replyTo,自定義的Parcelable對象沒法經過object字段來傳輸
  • Message中的Bundle支持多種數據類型,replyTo字段用於傳輸Messager對象,以便進程間相互通訊
  • Messager以串行的方式處理客戶端發來的消息,不適合有大量併發的請求
  • Messager方法只能傳遞消息,不能跨進程調用方法
使用AIDL
  • AIDL接口能夠經過編寫AIDL文件而後由系統生成對應的Binder類,經過Binder咱們就能夠進行跨進程通訊了
  • AIDL文件中只支持以下幾種類型:
    • 基本類型,如int、long等
    • String和CharSequence
    • List:只支持ArrayList,裏面的每一個元素都必須被AIDL支持
    • Map:只支持HashMap,裏面的key、value都必須被AIDL支持
    • AIDL:全部的AIDL接口自己也能夠在AIDL文件中使用
  • AIDL文件中用到的自定義Parcelable對象和AIDL對象必需要顯示的import進來
  • 出了基本數據類型,其餘類型的參數必須標明是入參仍是出參,in表示輸入型參數,out表示輸出型參數,inout表示輸入輸出型參數

序列化之Serializable接口和Parcelable接口

  • Serializable接口和Parcelable接口都能實現序列化,可是有區別
Serializable接口
  • Serializable接口實現序列化比較簡單,只須要在須要實現序列化的類實現Serializable接口就行
  • serialVersionUID能夠指定也能夠不指定,不指定的話系統會默認給咱們生成
  • serialVersionUID的做用是用於標識當前類的版本,便於在反序列化過程當中判斷類是否有更改,若是serialVersionUID不一致,反序列化就會失敗
  • 人爲指定serialVersionUID後,若是不是破壞性的改動了類,好比版本升級後增長了一個字段,那反序列化之後仍然能成功;而若是沒有指定,反序列化就會失敗
  • serialVersionUID是否指定須要根據具體的須要來肯定
  • 靜態成員變量和transient關鍵字標記的變量不參與序列化過程
Parcelable接口
  • Parcelable接口實現序列化稍微複雜,須要實現writeToParcel方法、describeContents方法以及生成器Creator
  • 內容描述功能的describeContents方法通常都返回0,噹噹前對象中存在文件描述符時才返回1
  • Parcelable接口中的Parcel內部包裝了可序列化的數據,能夠在Binder中自由傳輸
Parcelable接口和Serializable接口
  • Serializable接口是Java中的序列化接口,使用簡單可是開銷大,序列化和反序列化過程須要大量的I/O操做,通常用於將對象序列化到存儲設備中或是將對象序列化後經過網絡進行傳輸
  • Parcelable接口是Android中的序列化方式,使用稍微麻煩,可是效率很高,是Android中推薦的序列化方式,主要用在內存序列化上

歡迎關注個人微信公衆號,和我一塊兒學習一塊兒成長!
複製代碼

AntDream
相關文章
相關標籤/搜索