TShopping

 找回密碼
 註冊
搜索
查看: 668|回復: 0

[教學] Android中的Parcel是什麼

[複製鏈接]
發表於 2014-11-21 00:39:55 | 顯示全部樓層 |閱讀模式
 
Push to Facebook Push to Plurk Push to Twitter 

Parcel,翻譯過來是“打包”的意思。打包乾什麼呢?是為了序列化。

    如果要在進程之間傳遞一個整數,很簡單,直接傳就是行了;如果要傳一個字符串,就稍微複雜了點:需先分配一塊可以容納字符串的內存,然後將字符串複製到內存中,再傳遞(新手可能問:為啥不直接把字符串的引用傳過去呢?學過C/C++的地球人都知道:進程有自己的內存地址空間,一個進程中的1000地址可能在另一個進程中是100000,java對象的引用跟本上還是內存地址);再如果要傳遞一個類的實例呢?也是先為類分配內存,然後復制一份再傳遞可以嗎?我認為不可以,我至少可以找到一個理由:類中成員除了屬性還有方法,即使屬性能完整傳過去,但還有方法呢?方法是獨立於類對象存在的,所以到另一個進程中再引用同一個方法就要出錯了,還是因為獨立地址空間的原因。

    Android開發中,很經常在各activity之間傳遞數據,而跟據Android的設計架構,即使同一個程序中的Activity都不一定運行在同一個進程中,所以處理數據傳遞時你不能老假設兩個activity都運行於同一進程,那麼只能按進程間傳遞數據來處理,使之具有最廣泛的適應性。

  那麼到底如何在進程之間傳遞類對象呢?簡單來說可以這樣做:在進程A中把類中的非默認值的屬性和類的唯一標誌打成包(這就叫序列化),把這個包傳遞到進程B,進程B接收到包後,跟據類的唯一標誌把類創建出來,然後把傳來的屬性更新到類對像中,這樣進程A和進程B中就包含了兩個完全一樣的類對象。

  

Parcel是一個容器,它主要用於存儲序列化數據,然後可以通過Binder在進程間傳遞這些數據(要了解為什麼要序列化,請參考:http://blog.csdn.net/nkmnkm/archive/2011/05/28/6451699.aspx)。Parcel可以包含原始數據類型(用各種對應的方法寫入,比如writeInt(),writeFloat()等),可以包含Parcelable對象,它還包含了一個活動的IBinder對象的引用,這個引用導致另一端接收到一個指向這個IBinder的代理IBinder。

注:Parcel不是一般目的的序列化機制。這個類被設計用於高性能的IPC傳輸。因此不適合把Parcel寫入永久化存儲中,因​​為Parcel中的數據類型的實現的改變會導致舊版的數據不可讀。

  Parcel的一坨一坨的API用於解決不同類型數據的讀寫。這些函數們主要有六種類型。

1原始類

這類方法們主要讀寫原始數據類型。它們是:writeByte(byte), readByte(), writeDouble(double), readDouble(), writeFloat(float), readFloat(), writeInt(int), readInt(), writeLong(long), readLong(), writeString( String), readString().大多數其它數據的操作都是基於這些方法。

2原始數組類

這類方法用於讀寫原始數據組成的數組。在向數組寫數據時先寫入數組的長度再寫入數據。讀數組的方法可以將數據讀到已存在的數組中,也可以創建並返回一個新數組。它們是:

  • writeBooleanArray(boolean[]), readBooleanArray(boolean[]), createBooleanArray()
    writeByteArray(byte[]), writeByteArray(byte[], int, int), readByteArray(byte[]), createByteArray()
    writeCharArray(char[]), readCharArray(char[]), createCharArray()
    writeDoubleArray(double[]), readDoubleArray(double[]), createDoubleArray()
    writeFloatArray(float[]), readFloatArray(float[]), createFloatArray()
    writeIntArray(int[]), readIntArray(int[]), createIntArray()
    writeLongArray(long[]), readLongArray(long[]), createLongArray()
    writeStringArray(String[]), readStringArray(String[]), createStringArray().
    writeSparseBooleanArray(SparseBooleanArray), readSparseBooleanArray().



3 Parcelable類
Parcelable為對像從Parcel中讀寫自己提供了極其高效的協議。你可以使用直接的方法writeParcelable(Parcelable, int)和readParcelable(ClassLoader)或writeParcelableArray(T[], int) and readParcelableArray(ClassLoader)進行讀寫。這些方法們把類的信息和數據都寫入Parcel,以使將來能使用合適的類裝載器重新構造類的實例。

還有一些方法提供了更高效的操作Parcelable們的途徑,它們是:writeTypedArray(T[], int), writeTypedList(List), readTypedArray(T[], Parcelable.Creator) and readTypedList(List, Parcelable.Creator )。這些方法不會寫入類的信息,取而代之的是:讀取時必須能知道數據屬於哪個類並傳入正確的Parcelable.Creator來創建對象而不是直接構造新對象。(更加高效的讀寫單個Parcelable對象的方法是:直接調用Parcelable.writeToParcel()和Parcelable.Creator.createFromParcel())

4 Bundles類

Bundles是一種類型安全的Map型容器,可用於存儲任何不同類型的數據。它具有很多對讀寫數據的性能優化,並且它的類型安全機制避免了當把它的數據封送到Parcel中時由於類型錯誤引起的BUG的調試的麻煩,可以使用的方法為: writeBundle(Bundle ), readBundle(), and readBundle(ClassLoader)。

5 活動對像類

Parcel的一個非同尋常的特性是讀寫活對象的能力。對於活動對象,它們的內容實際上並沒有寫入,而是僅寫入了一個令牌來引用這個對象。當從Parcel中讀取這個對象時,你不會獲取一個新的對象實例,而是直接得到那個寫入的對象。有兩種活動對象可操作:

Binder對象。它是Android跨進程通訊的基礎。這種對象可被寫入Parcel,並在讀取時你將得到原始的對像或一個代理對象(可以想像:在進程內時得到原始的對象,在進程間時得到代理對象)。可以使用的方法們是: writeStrongBinder(IBinder), writeStrongInterface(IInterface), readStrongBinder(), writeBinderArray(IBinder[]), readBinderArray(IBinder[]), createBinderArray(), writeBinderList(List), readBinderList(List), createBinderArrayList ()。

FileDescriptor對象。它代表了原始的Linux文件描述符,它可以被寫入Parcel並在讀取時返回一個ParcelFileDescriptor對像用於操作原始的文件描述符。ParcelFileDescriptor是原始描述符的一個複制:對象和fd不同,但是都操作於同一文件流,使用同一個文件位置指針,等等。可以使用的方法是:writeFileDescriptor(FileDescriptor), readFileDescriptor()。

6無類型容器類

    一類final方法,用於讀寫標準的java容器類。這些方法們是:writeArray(Object[]), readArray(ClassLoader), writeList(List), readList(List, ClassLoader), readArrayList(ClassLoader), writeMap(Map), readMap(Map, ClassLoader), writeSparseArray(SparseArray) , readSparseArray(ClassLoader)。



 

臉書網友討論
您需要登錄後才可以回帖 登錄 | 註冊 |

本版積分規則



Archiver|手機版|小黑屋|免責聲明|TShopping

GMT+8, 2016-12-10 01:44 , Processed in 0.053966 second(s), 22 queries .

本論壇言論純屬發表者個人意見,與 TShopping綜合論壇 立場無關 如有意見侵犯了您的權益 請寫信聯絡我們。

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表