安卓中,Serializable和Parcelable傳遞對象的區(qū)別(這里只指使用 Binder 跨進(jìn)程傳遞對象),Binder 傳遞數(shù)據(jù),要通過在Binder的onTransact和transact方法里,通過 Parcel 對象傳遞,而Parcel對象,只支持傳遞幾種基本類型(與java基本數(shù)據(jù)類型有些差異,但請忽略這些細(xì)節(jié),后面統(tǒng)稱基本類型)。
對象發(fā)送時
- Parcelable使用者將組成對象的成員變量全部細(xì)化成基礎(chǔ)數(shù)據(jù)類型,通過Parcel進(jìn)而使用Binder傳遞,也就是如果成員變量不是基本類型,其也要實現(xiàn)Parcelable,直到全部都是基本類型,其傳遞的變量選擇由使用者手動控制,所以其實現(xiàn)也更麻煩,這個過程就是程序員用Parcel往Binder裝數(shù)據(jù)。
- 而Serializable要先用流將整個對象轉(zhuǎn)為byte數(shù)組,再用Binder將這個byte數(shù)組作為基本類型傳遞,這個過程由Parcel封裝,所以其使用簡單,不需要手寫代碼往Parcel里面裝數(shù)據(jù),Parcel封裝了將Serializable對象序列化成byte數(shù)組的過程。
對象接收時
- Parcelable 可以根據(jù)使用者的定義來創(chuàng)建對象,可以直接使用構(gòu)造函數(shù)創(chuàng)建(在Creator的createFromParcel),用Parcel從Binder中取出數(shù)據(jù)來初始化這個對象。
- Serializable 對象接收時是把Binder傳遞過來的byte數(shù)組通過流轉(zhuǎn)為對象,這個過程也是Parcel封裝的,其消耗更大,但使用者代碼量很少(幾乎什么都不用寫)。
簡單的來說,Parcelable對象發(fā)送時,由使用者將要傳遞的數(shù)據(jù)寫進(jìn)Parcel對象再傳遞至Binder中,對象接收時,使用者用 Parcel 從 Binder 中取值,完成對象的創(chuàng)建以及成員變量的賦值,使用者要清楚自己寫值和取值的順序。
Serializable 對象發(fā)送時,使用者只需要實現(xiàn) Serializable 接口,因為 Binder 只傳遞基本類型,Parcel 先將Serializable 對象序列化,整個轉(zhuǎn)為 byte 數(shù)組,然后通過 Binder 傳遞。對象接收時,通過 Parcel 從 Binder 讀出 byte 數(shù)組,再反序列化成對象,這個過程也是 Parcel 封裝的,所以使用者幾乎什么都不用做。
異同
- 兩者數(shù)據(jù)都要用 Binder 傳遞,接收對象時其實還都要用到反射(用Parcelable只是有可能用到反射,在androidstudio 生成的parcelable實現(xiàn)中,對于對象反序列化時拿T.CREATOR 對象其實用到反射拿到的,盡管這不是必須的)
- Parcelable 的使用由程序員從對象抽出數(shù)據(jù)寫入 Binder,在 Binder 另一端將零散的數(shù)據(jù)再組合成對象,而Serializable 由 Parcel 完成整個對象數(shù)據(jù)的打包,打包成一個 byte 數(shù)組,再在 Binder 的另一端解包再合成對象,所以使用者只操作對象而不具體操作數(shù)據(jù)。
Binder 讀寫數(shù)據(jù)的兩個過程中,Serializable 用到的中間對象更多,浪費的空間更多,傳遞的數(shù)據(jù)更大,浪費的時間也更多,但 Serializable 的好處,就是使用更簡單,而且可以脫離 Binder 使用,比如可以存對象到文件,或用 socket 傳遞對象,而 Parcelable 是完全依賴 Binder 的,Binder 負(fù)責(zé)數(shù)據(jù)的傳遞,而數(shù)據(jù)的提取和組合是使用者完成的,當(dāng)然,現(xiàn)在這些工作可以由插件工具一鍵生成,但這就是在代碼編寫階段的事情了(其實要想利用其他傳輸機(jī)制實現(xiàn) Parcelable 對象傳遞也是可以的,只要你能為其他機(jī)制實現(xiàn)一個擁有Parcel相同能力的類),