淺談Android IPC機(jī)制之Binder的工作機(jī)制
進(jìn)程和線程的關(guān)系
按照操作系統(tǒng)中的描述,線程是CPU調(diào)度的最小單位,同時線程也是一種有限的系統(tǒng)資源。而進(jìn)程一般是指一個執(zhí)行單元,在pc端或者移動端上是指一個程序或者一個應(yīng)用。一個進(jìn)程中可以包含一個或者是多個線程。所以他們的關(guān)系應(yīng)該是包含和被包含的關(guān)系。
跨進(jìn)程的種類
在Android中跨進(jìn)程通信的方式有很多種,Bundle,文件共享,AIDL,Messenger,ContentProvider,Socket,這些都能實(shí)現(xiàn)進(jìn)程間之間的通信,當(dāng)然,雖然都能夠?qū)崿F(xiàn)進(jìn)程間通信,但是他們之間的實(shí)現(xiàn)原理或者說是底層的實(shí)現(xiàn)方式都是不一樣的。下面,我們將會一一說明。
注:很多同學(xué)覺得創(chuàng)建進(jìn)程就應(yīng)該創(chuàng)建一個新的應(yīng)用。其實(shí)不是的。只要我們在AndroidMenifest上加上這一句代碼就可以了android:process=“:remote”具體的,同學(xué)們可以自己的了解。
在說IPC之前,先說一下一些基礎(chǔ)概念,這樣對后面的內(nèi)容能夠更好的理解。
Serializable,Parcelable接口
Serializable接口是java提供的一個序列化的接口,這是一個空的接口,為對象提供標(biāo)準(zhǔn)的序列化和反序列化操作。
Serializable序列化和反序列化,都是采ObjectOutputStream和ObjectInputStream就可以實(shí)現(xiàn),當(dāng)然這些系統(tǒng)基本已經(jīng)為我們實(shí)現(xiàn)了。
Parcelable接口,是Android自帶的一種序列化方式。序列化和反序列化都是通過writeToParcel方法來完成的。
兩者的區(qū)別:Serializable是java的序列化接口使用簡單,但是由于序列化和反序列化的過程需要大量的I/o操作,所以性能較差。Parcelable接口使用較為麻煩,但是效率很高,但是存在一個很大的缺點(diǎn),就是被Parcelable將對象序列化以后,要將對象保存到磁盤中的,將會很麻煩。所以建議是使用Serializable。
Binder
直觀來說,Binder是Android中的一個類,它實(shí)現(xiàn)了IBinder接口,從IPC的角度來說,Binder是Android中的一種跨進(jìn)程通信的一種方式,同時還可以理解為是一種虛擬的物理設(shè)備,它的設(shè)備驅(qū)動是/dev/binder/。從Framework角度來說,Binder是ServiceManager的橋梁。從應(yīng)用層來說,Binder是客戶端和服務(wù)端進(jìn)行通信的媒介。
在Android開發(fā)中,Binder主要用在Service中,包括AIDL和Messenger,由于Messenger的底層其實(shí)就是Aidl,所以現(xiàn)在我們以AIDL來分析一下binder的工作機(jī)制。
上代碼:
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: /Users/huangjialin/MyApplication/service/src/main/aidl/aidl/MyAIDLService.aidl
*/
package aidl;
// Declare any non-default types here with import statements
public interface MyAIDLService extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements aidl.MyAIDLService {
private static final java.lang.String DESCRIPTOR = "aidl.MyAIDLService";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an aidl.MyAIDLService interface,
* generating a proxy if needed.
*/
public static aidl.MyAIDLService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof aidl.MyAIDLService))) {
return ((aidl.MyAIDLService) iin);
}
return new aidl.MyAIDLService.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getString: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _result = this.getString();
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements aidl.MyAIDLService {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public java.lang.String getString() throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getString, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_getString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public java.lang.String getString() throws android.os.RemoteException;
}
上面這段代碼是系統(tǒng)生成的,在gen目錄下可以看到根據(jù)MyAIDLService.aidl系統(tǒng)為我們生成了MyAIDLService.java這個類。我們先來了解一下這個類中每個方法的含義:
DESCRIPTOR:Binder的唯一標(biāo)識,一般用于當(dāng)前Binder的類名表示。
asInterface(android.os.IBinder obj):用于將服務(wù)端的Binder對象轉(zhuǎn)換成客戶端所需的AIDL接口類型的對象,這種轉(zhuǎn)化過程是區(qū)分進(jìn)程的,如果客戶端和服務(wù)端位于同一個進(jìn)程,那么這個方法返回的是服務(wù)端的stub對象本身,否則返回的是系統(tǒng)封裝后的Stub.proxy對象。
asBinder():用于返回當(dāng)前Binder對象。
onTransact:該方法運(yùn)行在服務(wù)端的Binder線程池中,當(dāng)客戶端發(fā)起跨進(jìn)程通信請求的時候,遠(yuǎn)程請求通過系統(tǒng)底層封裝后交給該方法處理。注意這個方法public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags),服務(wù)端通過code可以確定客戶端所請求的目標(biāo)方法是什么,接著從data中取出目標(biāo)方法所需的參數(shù),然后執(zhí)行目標(biāo)方法。當(dāng)目標(biāo)方法執(zhí)行完畢后,就像reply中寫入返回值。這個方法的執(zhí)行過程就是這樣的。如果這個方法返回false,客戶端是會請求失敗的,所以我們可以在這個方法中做一些安全驗(yàn)證。
public java.lang.String getString() throws android.os.RemoteException:
這個方法運(yùn)行在客戶端中,當(dāng)客戶端調(diào)用此方法的時候,它的內(nèi)部實(shí)現(xiàn)是這樣的:首先創(chuàng)建該方法所需要的輸入類型Parcel對象_data,然后調(diào)用transact方法發(fā)起遠(yuǎn)程調(diào)用請求,同時當(dāng)前線程掛起,然后服務(wù)端的OnTransact方法會被調(diào)用,直到RPC過程返回后,當(dāng)前線程繼續(xù)執(zhí)行,并從_reply中讀取返回的數(shù)據(jù)。
如圖:Binder的工作機(jī)制

從上面分析,我們明白了Binder的工作機(jī)制但是要注意一些問題:
1.當(dāng)客戶端發(fā)起請求時,由于當(dāng)前線程會被掛起,直到服務(wù)端返回?cái)?shù)據(jù),如果這個遠(yuǎn)程方法很耗時的話,那么是不能夠在UI線程,也就是主線程中發(fā)起這個遠(yuǎn)程請求的。
2.由于Service的Binder方法運(yùn)行在線程池中,所以Binder方法不管是耗時還是不耗時都應(yīng)該采用同步的方式,因?yàn)樗呀?jīng)運(yùn)行在一個線程中了。
以上就是淺談Android IPC機(jī)制之Binder的工作機(jī)制的詳細(xì)內(nèi)容,更多關(guān)于Android IPC機(jī)制之Binder的工作機(jī)制的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android compose氣泡升起和水滴下墜動畫實(shí)現(xiàn)示例
這篇文章主要為大家介紹了Android compose氣泡升起和水滴下墜動畫實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Android自定義ViewGroup嵌套與交互實(shí)現(xiàn)幕布全屏滾動
這篇文章主要為大家介紹了Android自定義ViewGroup嵌套與交互實(shí)現(xiàn)幕布全屏滾動效果示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Android編程實(shí)現(xiàn)類似天氣預(yù)報(bào)圖文字幕垂直滾動效果的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)類似天氣預(yù)報(bào)圖文字幕垂直滾動效果的方法,涉及Android基于布局及事件響應(yīng)實(shí)現(xiàn)圖文滾動效果的相關(guān)操作技巧,需要的朋友可以參考下2017-08-08
Android開發(fā)實(shí)現(xiàn)撥打電話與發(fā)送信息的方法分析
這篇文章主要介紹了Android開發(fā)實(shí)現(xiàn)撥打電話與發(fā)送信息的方法,結(jié)合實(shí)例形式分析了Android撥打電話及發(fā)送信息相關(guān)布局、功能實(shí)現(xiàn)及權(quán)限控制操作技巧,需要的朋友可以參考下2017-12-12
詳解Android studio實(shí)現(xiàn)語音轉(zhuǎn)文字功能
這篇文章主要介紹了如何通過Android studio調(diào)用科大訊飛的語音轉(zhuǎn)文字功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-03-03

