1. 程式人生 > >android開發之Parcelable使用詳解

android開發之Parcelable使用詳解

想要在兩個activity之間傳遞物件,那麼這個物件必須序列化,android中序列化一個物件有兩種方式,一種是實現Serializable介面,這個非常簡單,只需要宣告一下就可以了,不痛不癢。但是android中還有一種特有的序列化方法,那就是實現Parcelable介面,使用這種方式來序列化的效率要高於實現Serializable介面。不過Serializable介面實在是太方便了,因此在某些情況下實現這個介面還是非常不錯的選擇。
使用Parcelable步驟:
1.實現Parcelable介面
2.實現介面中的兩個方法

public int describeContents();
public
void writeToParcel(Parcel dest, int flags);

第一個方法是內容介面描述,預設返回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即可 */ @Override public int describeContents() { return 0; } /** * 把值寫入Parcel中 */ @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(username); dest.writeString(nickname); dest.writeInt(age); } public static final Creator<Person> CREATOR = new Creator<Person>() { /** * 供外部類反序列化本類陣列使用 */ @Override public Person[] newArray(int size) { return new Person[size]; } /** * 從Parcel中讀取資料 */ @Override public Person createFromParcel(Parcel source) { return new Person(source); } }; }

最後貼上Parcelable原始碼,Google已經給了一個示例了:

/*
 * 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&lt;MyParcelable&gt; CREATOR
 *             = new Parcelable.Creator&lt;MyParcelable&gt;() {
 *         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);
    }
}