Android中的IPC機制

cryAllen發表於2017-01-22

Android IPC簡介

IPC是Inter-Process Communication的縮寫,含義就是程式間通訊或者跨程式通訊,是指兩個程式之間進行資料交換的過程。那麼什麼是程式,什麼是執行緒,程式和執行緒是兩個截然不同的概念。在作業系統中,執行緒是CPU排程的最小單元,同時執行緒是一種有限的系統資源。而程式指的一個執行單元,在PC和移動裝置上指的是一個程式或者一個應用。一個程式可以包含多個執行緒,因此程式和執行緒是包含被包含的關係,最簡單情況下,一個程式可以只有一個執行緒,即主執行緒,在Android裡面也叫UI執行緒,在UI執行緒裡才能操作介面元素。

那麼在Android中,有特色的程式間通訊方式就是Binder了,通過Binder可以輕鬆實現程式間通訊。除了Binder,Android還支援Socket,通過Socket也可以實現任意兩個終端之間的通訊,當然一個裝置上的兩個程式之間通過Socket通訊自然也是可以的。

說到IPC的使用場景就必須提到多程式,只有面對多程式這種場景下,才需要考慮程式間通訊。所有執行在不同程式中的四大元件,只要它們之間需要通過記憶體來共享資料,都會共享失敗,這也是多程式所帶來的主要影響。正常情況下,四大元件中間不可能不通過一些中間層來共享資料,那麼通過簡單地指定程式名來開啟多程式都會無法正確執行。一般來說,使用多程式會造成如下幾方面的問題:

  • 靜態成員和單例模式完全失效
  • 執行緒同步機制完全失效
  • SharedPreferences的可靠性下降
  • Application會多次建立

為了解決這個問題,系統提供了很多跨程式通訊方法,雖然說不能直接地共享記憶體,但是通過跨程式通訊我們還是可以實現資料互動。實現跨程式通訊的方式有很多,比如通過Intent來傳遞資料,共享檔案SharedPreference,基於Binder的Messenger和AIDL以及Socket等。

IPC基礎概念介紹

Serializable介面

Serializable是Java提供的一個序列化介面,它是一個空介面,為物件標準的序列化和反序列化操作。使用Serializable來實現序列化相當簡單,一句話即可。

public class User implements Serializable {
  private static final long seriaVersionUID = 519067123721295773L
}

Parcelable介面

Parcel內部包裝了可序列化的資料,可以在Binder中自由傳輸,在序列化過程中需要實現的功能有序列化、反序列化和內容描述序列化功能有writeToParcel方法來完成,最終是通過Parcel中的一系列write方法來完成的。用法如下:

public class MyParcelable implements Parcelable {
    // You can include parcel data types
    private int mData;
    private String mName;
    
    // We can also include child Parcelable objects. Assume MySubParcel is such a Parcelable:
    private MySubParcelable mInfo;

    // This is where you write the values you want to save to the `Parcel`.  
    // The `Parcel` class has methods defined to help you save all of your values.  
    // Note that there are only methods defined for simple values, lists, and other Parcelable objects.  
    // You may need to make several classes Parcelable to send the data you want.
    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mData);
        out.writeString(mName);
        out.writeParcelable(mInfo, flags);
    }

    // Using the `in` variable, we can retrieve the values that 
    // we originally wrote into the `Parcel`.  This constructor is usually 
    // private so that only the `CREATOR` field can access.
    private MyParcelable(Parcel in) {
        mData = in.readInt();
        mName = in.readString();
        mInfo = in.readParcelable(MySubParcelable.class.getClassLoader());
    }

    public MyParcelable() {
        // Normal actions performed by class, since this is still a normal object!
    }

    // In the vast majority of cases you can simply return 0 for this.  
    // There are cases where you need to use the constant `CONTENTS_FILE_DESCRIPTOR`
    // But this is out of scope of this tutorial
    @Override
    public int describeContents() {
        return 0;
    }

    // After implementing the `Parcelable` interface, we need to create the 
    // `Parcelable.Creator<MyParcelable> CREATOR` constant for our class; 
    // Notice how it has our class specified as its type.  
    public static final Parcelable.Creator<MyParcelable> CREATOR
            = new Parcelable.Creator<MyParcelable>() {

        // This simply calls our new constructor (typically private) and 
        // passes along the unmarshalled `Parcel`, and then returns the new object!
        @Override
        public MyParcelable createFromParcel(Parcel in) {
            return new MyParcelable(in);
        }

        // We just need to copy this and change the type to match our class.
        @Override
        public MyParcelable[] newArray(int size) {
            return new MyParcelable[size];
        }
    };
}

Serializable和Parcelable區別

Serializable是Java中的序列化介面,其使用起來簡單但是開銷很大,在序列化和反序列化過程中需要大量的I/O操作。而Parcelable是Android中的序列化方式,因此更適合用在Android平臺上,它的缺點就是使用起來稍微麻煩點,但是它的效率很高。

Binder
直觀來說,Binder是Android中的一個類,它實現了IBinder介面。從IPC角度來說,Binder是Android中的一種跨程式通訊方式,Binder還可以理解為一種虛擬的物理裝置,它的裝置驅動是/dev/binder,該通訊方式在Linux中沒有。從Android Framework角度來說,Binder是ServiceManager連線各種Manager(ActivityManager、WindowManager等等)和相應ManagerService的橋樑。從Android應用層來說,Binder是客戶端和服務端進行通訊的媒介,當bindService的時候,服務端會返回一個包含了服務端業務呼叫的Binder物件,通過Binder物件,客戶端就可以獲取服務端提供的服務或者資料,這裡的服務包括普通服務和基於AIDL的服務。

Binder工作機制

Android中的IPC方式

使用Bundler

我們知道,四大元件中三大元件(activity、service、receiver)都是支援在Intent中傳遞Bundle資料的,由於Bundle實現了Parcelable介面,所以它可以方便地在不同的程式間傳輸。

使用檔案共享

共享檔案也是一種不錯的程式間通訊方式,兩個程式間通過讀/寫同一個檔案來交換資料,比如A程式把資料寫入檔案,B程式通過讀取這個檔案來獲取資料。

使用Messenger

Messenger可以翻譯為信使,顧名思義,通過它可以在不同程式中傳遞Message物件,在Message中放入我們需要傳遞的資料,就可以輕鬆地實現資料的程式間傳遞。Messenger是一種輕量級的IPC方案,它的底層實現是AIDL,實現Messenger有以下兩個步驟,分為服務端程式和客戶端程式。

Messenger工作原理

使用AIDL

遠端服務跨程式通訊的一種方式。

使用ContentProvider

ContentProvider是Android中提供的專門用於不同應用間進行資料共享的方式,它的底層實現同樣也是Binder。

使用Socket

Socket也稱為“套接字”,是網路通訊中的概念,它分為流式套接字和使用者資料套接字兩種,分別應於網路的傳輸控制層中的TCP和UDP協議。

選用合適的IPC方式

不同IPC方式比較

閱讀擴充套件

源於對掌握的Android開發基礎點進行整理,羅列下已經總結的文章,從中可以看到技術積累的過程。
1,Android系統簡介
2,ProGuard程式碼混淆
3,講講Handler+Looper+MessageQueue關係
4,Android圖片載入庫理解
5,談談Android執行時許可權理解
6,EventBus初理解
7,Android 常見工具類
8,對於Fragment的一些理解
9,Android 四大元件之 " Activity "
10,Android 四大元件之" Service "
11,Android 四大元件之“ BroadcastReceiver "
12,Android 四大元件之" ContentProvider "
13,講講 Android 事件攔截機制
14,Android 動畫的理解
15,Android 生命週期和啟動模式
16,Android IPC 機制
17,View 的事件體系
18,View 的工作原理
19,理解 Window 和 WindowManager
20,Activity 啟動過程分析
21,Service 啟動過程分析
22,Android 效能優化
23,Android 訊息機制
24,Android Bitmap相關
25,Android 執行緒和執行緒池
26,Android 中的 Drawable 和動畫
27,RecylerView 中的裝飾者模式
28,Android 觸控事件機制
29,Android 事件機制應用
30,Cordova 框架的一些理解
31,有關 Android 外掛化思考
32,開發人員必備技能——單元測試

相關文章