轉:http://blog.csdn.net/sergeycao/article/details/52585411android
談transact 和onTransact須要先聊聊iBinder併發
IBinder是什麼呢?首先要明白,Android的遠程調用(就是跨進程調用)就是經過IBinder實現的,下面是對android開發文檔的翻譯。工具
IBinder是遠程對象的基本接口,是爲高性能而設計的輕量級遠程調用機制的核心部分。但它不只用於遠程調用,也用於進程內調用。這個接口定義了與遠程對象交互的協議。不要直接實現這個接口,而應該從Binder派生。
IBinder的主要API是transact(),與它對應另外一方法是Binder.onTransact()。第一個方法使你能夠向遠端的IBinder對象發送發出調用,第二個方法使你本身的遠程對象可以響應接收到的調用。IBinder的API都是同步執行的,好比transact()直到對方的Binder.onTransact()方法調用完成後才返回。調用發生在進程內時無疑是這樣的,而在進程間時,在IPC的幫助下,也是一樣的效果。
經過transact()發送的數據是Parcel,Parcel是一種通常的緩衝區,除了有數據外還帶有一些描述它內容的元數據。元數據用於管理IBinder對象的引用,這樣就能在緩衝區從一個進程移動到另外一個進程時保存這些引用。這樣就保證了當一個IBinder被寫入到Parcel併發送到另外一個進程中,若是另外一個進程把同一個IBinder的引用回發到原來的進程,那麼這個原來的進程就能接收到發出的那個IBinder的引用。這種機制使IBinder和Binder像惟一標誌符那樣在進程間管理。
系統爲每一個進程維護一個存放交互線程的線程池。這些交互線程用於派送全部從另外進程發來的IPC調用。例如:當一個IPC從進程A發到進程B,A中那個發出調用的線程(這個應該不在線程池中)就阻塞在transact()中了。進程B中的交互線程池中的一個線程接收了這個調用,它調用Binder.onTransact(),完成後用一個Parcel來作爲結果返回。而後進程A中的那個等待的線程在收到返回的Parcel後得以繼續執行。實際上,另外一個進程看起來就像是當前進程的一個線程,但不是當前進程建立的。
Binder機制還支持進程間的遞歸調用。例如,進程A執行本身的IBinder的transact()調用進程B的Binder,而進程B在其Binder.onTransact()中又用transact()向進程A發起調用,那麼進程A在等待它發出的調用返回的同時,還會用Binder.onTransact()響應進程B的transact()。總之Binder形成的結果就是讓咱們感受到跨進程的調用與進程內的調用沒什麼區別。
當操做遠程對象時,你常常須要查看它們是否有效,有三種方法可使用:
1 transact()方法將在IBinder所在的進程不存在時拋出RemoteException異常。
2 若是目標進程不存在,那麼調用pingBinder()時返回false。
3 能夠用linkToDeath()方法向IBinder註冊一個IBinder.DeathRecipient,在IBinder表明的進程退出時被調用。
要實現IBinder來支持遠程調用,應從Binder類派生一個類。Binder實現了IBinder接口。可是通常不須要直接實現此類,而是跟據你的須要由開發包中的工具生成,這個工具叫AIDL。你經過AIDL語言定義遠程對象的方法,而後用AIDL工具生成Binder的派生類,而後就可以使用之。然而,但是,可是,固然,你也能夠直接從Binder類派生以實現自定義的RPC調用,或只是實例化一個原始的Binder對象直接做爲進程間共享的令牌來使用。