Android中的IPC機制


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,開發人員必備技能——單元測試


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM