基于安卓平台的序列化與反序列化封裝元件Parceler ( https://github.com/johncarl81/parceler ),實作了鴻蒙化遷移和重構,代碼已經開源到( https://gitee.com/isrc_ohos/parceler_ohos ),目前已經獲得了很多人的Star和Fork ,歡迎各位下載下傳使用并提出寶貴意見!
序列化是指将Java對象轉換為位元組序列的過程,本質上是把實體對象狀态按照一定的格式寫入到有序位元組流;而反序列化則是将位元組序列轉換為Java對象的過程,本質上是從有序位元組流重建對象,恢複對象狀态。當兩個Java程序互相通信時,就需要使用Java序列化與反序列化方法來實作程序間的對象傳送。鴻蒙中Parceler_ohos元件可将不同種類型的資料進行序列化和反序列化封裝,進而達到程序間對象傳送的效果。
Parceler_ohos元件支援多種資料的序列化和反序列化處理,包括基礎資料類、數組、Map類、Set類、以及序列化資料類,各類型中包含的具體資料類如下:
基礎資料類:int、float、String、boolean......;
數組:PlainArray、PlainBooleanArray;
Map類:Map、HashMap、LinkedHashMap......;
Set類:Set、HashSet、SortedSet......;
序列化資料類:Sequensable、Serializable。
元件以上述資料中的五種為例進行序列化和反序列化示範,分别是:int、float、String、plainArray、Sequenceable。
使用者點選元件圖示後進入“Parceler測試”主界面,該界 面包含“int測試”、“float測試”、“String測試”、“plainArray測試”、“Sequenceable測試”五個按鈕。點選上述各按鈕可跳轉至相應類型資料的序列化和反序列化測試界面。由于這五種資料的測試步驟相同,接下來就以元件中int資料的測試效果為例進行展示。
點選“int測試”按鈕進入“int格式測試”界面;再點選“開始測試”按鈕,即可将事先設定好的整型測試資料“34258235”轉換成序列化位元組流,并将序列化結果顯示在文字“序列化:”的下方;然後将位元組流反序列化并輸出,輸出内容為序列化之前的對象“34258235”;點選“傳回”按鈕後則可跳轉回主界面,上述測試效果如圖1所示。
::: hljs-center

圖1 int資料序列化與反序列化測試
:::
Sample工程檔案中的MainMenu檔案用于建構元件應用的主界面,其他檔案用于建構上述元件效果展示的五種資料的序列化和反序列化測試界面,其對應關系如圖2所示。由于各種資料的測試步驟相同,下文将以int資料的序列化和反序列化測試為例進行詳細講解,其他資料類型不再贅述。
圖 2 Sample中各檔案與測試界面中按鈕的對應關系
主界面的布局比較簡單,主要是設定進入五種資料測試界面的按鈕,具體步驟如下:
第1步:聲明五種資料的測試按鈕和标題。
第2步:建立頁面布局。
第3步:為int資料測試按鈕設定監聽。
第4步:建立int資料測試按鈕。
聲明用于顯示标題“Parceler測試”的Text文本,以及用于跳轉到具體測試界面的5個Button按鈕,并将它們分别按類型命名。
建立一個縱向顯示的整體頁面布局,其寬度和高度都跟随父控件變化而調整,上下左右四個方向的填充間距依次是10/32/10/80,并設定背景顔色為白色。
對int資料測試按鈕設定onClick()點選監聽事件,實作點選按鈕可跳轉至int資料測試界面的效果。具體代碼如下。
Sample中包含的5個測試按鈕除了顯示的文本資訊和按鈕監聽事件不同以外,其他屬性完全一緻,這些屬性包括:按鈕顔色、倒角、顯示文本大小、對齊方式、按鈕内填充距離等。
上文中我們已經對主界面布局的實作進行了介紹,接下來就具體以int型資料序列化和反序列化測試為例,為大家講解如何使用Parceler_ohos元件。該元件處理int類型的資料共分為4個步驟:
第1步:導入相關類。
第2步:建立布局。
第3步:設定輸入資料和輸出資料。
第4步:建立測試按鈕。
在IntTest檔案中,通過import關鍵字導入Parcels類,該類提供了資料序列化和反序列化實作的具體方法。
建立一個縱向顯示的int資料測試頁面布局,寬度和高度都跟随父控件變化而調整,上下左右四個方向的填充間距依次是32/32/80/80,并設定背景顔色為白色。
首先設定一個int資料作為輸入資料,将測試資料的值34258235賦給int類對象intIn,并使用setText()方法将其以文本的形式顯示在界面上,格式為:“輸入:34258235”。然後分别執行個體化兩個Text類對象,一個是wrappedOutput,用來顯示輸入資料的序列化輸出,格式為"序列化:xxx",另一個是output,用來顯示上述序列化結果的反序列化輸出,格式為"輸出:xxx"。
界面上觸發序列化和反序列化操作的按鈕為“開始測試”按鈕。當該按鈕被點選後,會調用wrap()方法對輸入資料執行序列化操作,并将得到的位元組流資訊顯示在上述第3步實作的“序列化:”文本後方;調用unwrap()方法将序列化後的位元組流完成反序列化操作,并将得的整型對象輸出在上述第3步實作的的“輸出:”文本後方。
Parceler_ohos元件能夠針對不同類型的資料,進行序列化和反序列化的操作。在使用Parceler_ohos元件實作序列化和反序列化操作時,隻需分别調用Pacels類中的wrap()和unWrap()方法,并将待操作資料作為唯一參數傳入即可,具體使用方法在上文Sample解析中已有詳細講解,此處不再進行贅述。接下來分别從Parceler_ohos元件的序列化和反序列化方法原了解析、以及轉換器原理這兩個方面進行講解。
(1)wrap()方法實作序列化
實作序列化操作的原理和函數調用關系可以參考下圖3。
圖3 序列化操作原理示意圖
在Parcels類中,通過方法重載分别實作了兩種wrap()方法。第一種wrap()方法是直接被開發者調用的方法,僅有一個輸入資料作為參數,在判斷輸入資料不為空後,擷取輸入資料的具體資料類型并調用第二種wrap()方法。
第二種wrap()方法有兩個參數:輸入資料類型和資料本身。在判斷輸入資料不為空後,将輸入資料類型inputType作為ParcelCodeRepository類get()方法的參數,傳回一個Parcelable工廠類對象parcelableFactory;再通過parcelableFactory調用buildParcelable()方法,執行具體的序列化操作。
其中,parcelableFactory.buildParcelable(input)方法具體執行過程是:
a.實作泛型類接口
實作ParcelableFactory泛型類接口;再将輸入資料作為入參傳入buildParcelable(input)方法。
b.調用參數類型與輸入資料類型比對的buildParcelable(input)方法
在Libray的NonParcelRepository類中,有多個類實作了ParcelableFactory的接口,是以有多種參數形式的buildParcelable(input)方法,分别對應多種輸入的資料類型,如boolean、char、List、Integer、set等。當輸入資料為int類型時,就需要調用參數類型為Integer的buildParcelable(input)方法,并傳回新執行個體化的IntegerParcelable類對象。
c.執行個體化IntegerParcelable類對象
執行個體化轉換器類對象CONVERTER;再通過IntegerParcelable類的構造方法完成執行個體化操作,此步驟需要調用IntegerParcelable類父類的構造函數,以輸入資料和轉換器CONVERTER作為入參。
d.調用父類構造函數,實作轉換器類接口
在調用父類ConverterParcelable的構造函數時,先在相應轉換器類中實作TypeRangeParcelConverter類接口中的toParcel()和fromParcel()方法,然後調用相應轉換器類的toParcel()方法完成序列化操作,其中具體轉換器類實作原理會在下文進行詳細講解,此處不進行贅述。
(2) unwrap()方法實作反序列化
實作反序列化操作,在判斷輸入資料不為空後,将輸入資料的值賦給接口ParcelWrapper的泛型類對象,再通過類對象調用getParcel()方法,擷取輸入資料的反序列化結果。
其中,wrapper.getParcel()方法具體執行過程是:實作ParcelWrapper泛型類接口,并實作getParcel()方法來執行具體的反序列化操作;最後傳回反序列化後的“@Parcel”執行個體。
在上文講解序列化方法wrap()時提到Parceler_ohos元件的轉換器處理類是Converter類。這些類負責處理資料集合的各種複雜或冗長繁複的工作,如判空檢查和資料集合疊代,并被打包在名為converter的包中,以便在API的相應包下更容易地找到資料集合的轉換。這些轉換器處理類能夠對多種資料類型進行轉換,如基礎資料類、Map類和Set類等,其具體轉換原理大同小異,接下來就以字元串數組轉換器CharArrayParcelConverter類為例進行詳細講解。
CharArrayParcelConverter類中包含兩個主要方法,即toParcel()和fromParcel(),其實質是分别負責對Parcel類對象進行寫和讀操作。在toParcel()方法中,先判斷字元串資料是否為空,若為空則将數組資料寫入到Parcel類對象中,寫入資料為NULL;否則寫入資料為字元串數組,包括其長度和資料本身。
在fromParcel()方法中,先從Parcel類對象中讀取數組的長度,判斷長度是否為空,若為空則擷取到空值;否則執行個體化一個新的字元串數組,通過Parcel類對象調用readCharArray()方法讀取數組中的資料,以剛才新執行個體化的數組作為入參,這樣就可以将讀取到的資料存入新執行個體化的數組中,友善後續對讀取到的資料的使用和處理,再傳回新數組即可完成讀取。
項目貢獻人
吳聖垚 鄭森文 朱偉 陳美汝 李珂 張馨心
想了解更多關于鴻蒙的内容,請通路:
51CTO和華為官方戰略合作共建的鴻蒙技術社群
https://harmonyos.51cto.com/#bkwz