直觀來說窟绷,Binder是Android中的一個類柳畔,它實現(xiàn)了IBinder接口嘿歌。從IPC角度來說掸掏,Binder是Android中的一個中跨進(jìn)程通信方式。
Android開發(fā)中宙帝,Binder主要用在Service中丧凤,包括AIDL和Messenger其中普通Service中的Binder不涉及進(jìn)程間通訊,而Messenger的底層其實是AID步脓,這里選擇用AIDL來分析Binder的工作機制愿待。為了分析Binder工作機制,接下來需要新建一個AIDL示例
首先創(chuàng)建一個Book類實現(xiàn)Parcelable
然后創(chuàng)建IBookManager.aidl是我們定義的一個接口靴患,里面有倆個方法:getBookList和addBook仍侥,然后通過Android Studio ?Build-->Make Project
就會在app-->build-->generated-->source-->aidl-->debig-->包名-->IBookManager接口繼承IInterface接口詳細(xì)介紹一下每個方法的含義
DESCRIPTOR
?BInder的唯一標(biāo)識,一般用當(dāng)前Binder的類名標(biāo)識鸳君。
asInterface(android.os.IBinder obj)
? ? 用于將服務(wù)端Binder對象轉(zhuǎn)換成客戶端所需要的AIDL接口類型對象农渊,這種轉(zhuǎn)換過程是區(qū)分進(jìn)程的,如果客戶端和服務(wù)端位于統(tǒng)一進(jìn)程或颊,那么此方法返回的就是服務(wù)端的Stub對象本身砸紊,否則返回的就是系統(tǒng)封裝后的Stub.proxy對象
asBinder
此方法用于返回當(dāng)前Binder對象
onTransact
這個方法運行服務(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ù)(如果目標(biāo)方法有參數(shù)的話)唆涝,然后執(zhí)行目標(biāo)方法。當(dāng)目標(biāo)方法執(zhí)行完畢后唇辨,就向reply中寫入返回值(如果目標(biāo)方法有返回值的話)石抡,onTransact方法執(zhí)行過程就是這樣的。需要注意的是助泽,如果此方法返回false,那么客戶端的請求會失敗嚎京,因此我們可以利用這個特性來做權(quán)限驗證,畢竟我們也不希望隨便一個進(jìn)程都能遠(yuǎn)程調(diào)用我們的服務(wù)鞍帝。
Proxy#getBookList
? ? 這個方法運行在客戶端诫睬,當(dāng)客戶端遠(yuǎn)程調(diào)用此方法時,它的內(nèi)部實現(xiàn)是這樣的:首先創(chuàng)建該方法所需要的輸入性Parcel對象 data帕涌、輸出型Parcel對象 reply和返回對象List摄凡;然后把該方法的參數(shù)信息寫入data中(如果有參數(shù)的話)续徽;接著調(diào)用transact方法來發(fā)起RPC(遠(yuǎn)程過程調(diào)用)請求,同時當(dāng)前線程掛起亲澡;然后服務(wù)端的onTransact方法會被調(diào)用钦扭,知道RPC過程返回后,當(dāng)前線程繼續(xù)執(zhí)行床绪,并從reply中取出RPC過程返回結(jié)果值客情;最后返回reply中的數(shù)據(jù)。
通過上面分析癞己,已經(jīng)知道Binder的工作機制膀斋,但是有兩點還是需要注意一下:首先,當(dāng)客戶端發(fā)起遠(yuǎn)程請求時痹雅,由于當(dāng)前線程會被掛機直至服務(wù)端返回數(shù)據(jù)仰担,所有如果一個遠(yuǎn)程方法是很耗時的,那么不能在UI線程中發(fā)起此遠(yuǎn)程請求绩社;其次由于服務(wù)端的Binder方法運行在Binder線程池中摔蓝,所以Binder方法不管是否耗時都應(yīng)該采用同步的方式實現(xiàn)(不是很理解這句話)。
Binder有兩個很重要的方法linkToDeath和unlinkToDeath我們知道铃将,Binder運行在服務(wù)端進(jìn)程项鬼,如果服務(wù)端進(jìn)程由于某種原因異常終止,這個時候我們到服務(wù)端的Binder連接斷裂(稱之為Binder死亡)劲阎,會導(dǎo)致我們遠(yuǎn)程調(diào)用失敗绘盟。更為關(guān)鍵的是,如果我們不知道Binder連接已經(jīng)斷裂悯仙,那么客戶端的功能就會受到影響龄毡。為了很好的解決這個問題,Binder中提供了倆個配對的方法linkToDeath和unlinkToDeath锡垄,通過linToDeath我們可以給Binder設(shè)置一個死亡代理沦零,當(dāng)Binder死亡是,我們就會收到通知货岭,這個時候我們就可以重新發(fā)起連接請求路操。