android 如何使用Parcelable接口
今天,簡單講講android如何使用Parcelable接口傳遞數據。
這個其實也很簡單,之前我寫過博客將關于Serializable接口傳遞對象,實現Parcelable接口也是為了傳遞對象,但效率更高,所以在網上查找了相關的資料,這里記錄一下。
?
想要在兩個activity之間傳遞對象,那么這個對象必須序列化,android中序列化一個對象有兩種方式,一種是實現Serializable接口,這個非常簡單,只需要聲明一下就可以了,不痛不癢。但是android中還有一種特有的序列化方法,那就是實現Parcelable接口,使用這種方式來序列化的效率要高于實現Serializable接口。不過Serializable接口實在是太方便了,因此在某些情況下實現這個接口還是非常不錯的選擇。
?
1.實現序列化的方法
Android中實現序列化有兩個選擇:一是實現Serializable接口(是JavaSE本身就支持的),一是實現Parcelable接口(是Android特有功能,效率比實現Serializable接口高效,可用于Intent數據傳遞,也可以用于進程間通信(IPC))。實現Serializable接口非常簡單,聲明一下就可以了,而實現Parcelable接口稍微復雜一些,但效率更高,推薦用這種方法提高性能。
注:Android中Intent傳遞對象有兩種方法:一是Bundle.putSerializable(Key,Object),另一種是Bundle.putParcelable(Key,Object)。當然這些Object是有一定的條件的,前者是實現了Serializable接口,而后者是實現了Parcelable接口。
?
2.選擇序列化方法的原則
1)在使用內存的時候,Parcelable比Serializable性能高,所以推薦使用Parcelable。
2)Serializable在序列化的時候會產生大量的臨時變量,從而引起頻繁的GC。
3)Parcelable不能使用在要將數據存儲在磁盤上的情況,因為Parcelable不能很好的保證數據的持續性在外界有變化的情況下。盡管Serializable效率低點,但此時還是建議使用Serializable 。
2.使用Parcelable的步驟
1.實現Parcelable接口
2.實現接口中的兩個方法
第一個方法是內容接口描述,默認返回0就可以了
第二個方法是將我們的對象序列化一個Parcel對象,也就是將我們的對象存入Parcel中
3.實例化靜態內部對象CREATOR實現接口Parcelable.Creator,實例化CREATOR時要實現其中的兩個方法,其中createFromParcel的功能就是從Parcel中讀取我們的對象。
也就是說我們先利用writeToParcel方法寫入對象,再利用createFromParcel方法讀取對象,因此這兩個方法中的讀寫順序必須一致,否則會出現數據紊亂,一會我會舉例子。
public class Person implements Parcelable{private String username;private String nickname;private int age;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getNickname() {return nickname;}public void setNickname(String nickname) {this.nickname = nickname;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Person(String username, String nickname, int age) {super();this.username = username;this.nickname = nickname;this.age = age;}public Person() {super();}/*** 這里的讀的順序必須與writeToParcel(Parcel dest, int flags)方法中* 寫的順序一致,否則數據會有差錯,比如你的讀取順序如果是:* nickname = source.readString();* username=source.readString();* age = source.readInt();* 即調換了username和nickname的讀取順序,那么你會發現你拿到的username是nickname的數據,* 而你拿到的nickname是username的數據* @param source*/public Person(Parcel source) {username = source.readString();nickname=source.readString();age = source.readInt();}/*** 這里默認返回0即可*/@Overridepublic int describeContents() {return 0;}/*** 把值寫入Parcel中*/@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(username);dest.writeString(nickname);dest.writeInt(age);}public static final Creator<Person> CREATOR = new Creator<Person>() {/*** 供外部類反序列化本類數組使用*/@Overridepublic Person[] newArray(int size) {return new Person[size];}/*** 從Parcel中讀取數據*/@Overridepublic Person createFromParcel(Parcel source) {return new Person(source);}}; }簡單講講,其實實現Parcelable接口就是對對象序列化,使對象可以在Intent或進程之間傳遞。使用也很簡單,首先寫一個類,實現Parcelable接口,對每個變量設置get和set函數,然后重寫public int describeContents();,這個固定返回0就可以。還需要重寫public void writeToParcel(Parcel dest, int flags);這里面通過dest.writeString(username);將變量一個一個的序列化,然后在構造函數里寫一個獲取序列化數據的函數,參數為Parcel,比如public Person(Parcel source),通過source.readString()來一個一個的讀取變量。這里需要注意一點,讀取變量的順序必須和之前寫入變量的順序保持一致,不然會出錯。最后還需要實例化靜態內部對象CREATOR實現接口Parcelable.Creator,實例化CREATOR時要實現其中的兩個方法,其中createFromParcel的功能就是從Parcel中讀取我們的對象。public Person createFromParcel(Parcel source)和public Person[] newArray(int size)都是調用new Person(source)來讀取序列化變量的,只是createFromParcel是讀取一個對象,newArray是讀取一個數組。
?
這里還需要注意一點,Parcelable只能對內存對象序列化,不能對需要存儲在文件或SD等設備進行序列化,如果需要將對象序列化存儲到文件,實現Serializable接口就可以了。
最后貼上Parcelable源碼:
/** Copyright (C) 2006 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package android.os;/*** Interface for classes whose instances can be written to* and restored from a {@link Parcel}. Classes implementing the Parcelable* interface must also have a static field called <code>CREATOR</code>, which* is an object implementing the {@link Parcelable.Creator Parcelable.Creator}* interface.* * <p>A typical implementation of Parcelable is:</p>* * <pre>* public class MyParcelable implements Parcelable {* private int mData;** public int describeContents() {* return 0;* }** public void writeToParcel(Parcel out, int flags) {* out.writeInt(mData);* }** public static final Parcelable.Creator<MyParcelable> CREATOR* = new Parcelable.Creator<MyParcelable>() {* public MyParcelable createFromParcel(Parcel in) {* return new MyParcelable(in);* }** public MyParcelable[] newArray(int size) {* return new MyParcelable[size];* }* };* * private MyParcelable(Parcel in) {* mData = in.readInt();* }* }</pre>*/ public interface Parcelable {/*** Flag for use with {@link #writeToParcel}: the object being written* is a return value, that is the result of a function such as* "<code>Parcelable someFunction()</code>",* "<code>void someFunction(out Parcelable)</code>", or* "<code>void someFunction(inout Parcelable)</code>". Some implementations* may want to release resources at this point.*/public static final int PARCELABLE_WRITE_RETURN_VALUE = 0x0001;/*** Bit masks for use with {@link #describeContents}: each bit represents a* kind of object considered to have potential special significance when* marshalled.*/public static final int CONTENTS_FILE_DESCRIPTOR = 0x0001;/*** Describe the kinds of special objects contained in this Parcelable's* marshalled representation.* * @return a bitmask indicating the set of special object types marshalled* by the Parcelable.*/public int describeContents();/*** Flatten this object in to a Parcel.* * @param dest The Parcel in which the object should be written.* @param flags Additional flags about how the object should be written.* May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.*/public void writeToParcel(Parcel dest, int flags);/*** Interface that must be implemented and provided as a public CREATOR* field that generates instances of your Parcelable class from a Parcel.*/public interface Creator<T> {/*** Create a new instance of the Parcelable class, instantiating it* from the given Parcel whose data had previously been written by* {@link Parcelable#writeToParcel Parcelable.writeToParcel()}.* * @param source The Parcel to read the object's data from.* @return Returns a new instance of the Parcelable class.*/public T createFromParcel(Parcel source);/*** Create a new array of the Parcelable class.* * @param size Size of the array.* @return Returns an array of the Parcelable class, with every entry* initialized to null.*/public T[] newArray(int size);}/*** Specialization of {@link Creator} that allows you to receive the* ClassLoader the object is being created in.*/public interface ClassLoaderCreator<T> extends Creator<T> {/*** Create a new instance of the Parcelable class, instantiating it* from the given Parcel whose data had previously been written by* {@link Parcelable#writeToParcel Parcelable.writeToParcel()} and* using the given ClassLoader.** @param source The Parcel to read the object's data from.* @param loader The ClassLoader that this object is being created in.* @return Returns a new instance of the Parcelable class.*/public T createFromParcel(Parcel source, ClassLoader loader);} }?
android 如何使用Parcelable接口就講完了。
?
就這么簡單。
總結
以上是生活随笔為你收集整理的android 如何使用Parcelable接口的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 如何保留数据两位小数
- 下一篇: android studio如何生成混淆