Intent 或持久化存儲處理複雜對象

歡迎Follow我的GitHub: https://github.com/SpikeKing

Logo

本文的合集已經編著成書,高級Android開發強化實戰,歡迎各位讀友的建議和指導。在京東即可購買:https://item.jd.com/12385680.html

Book

在進程或頁面通信時需要使用Intent傳遞數據; 在對象持久化時需要存儲數據. 對於複雜的對象, 進行序列化纔可傳遞或存儲, 可以使用Java的Serializable方式或Android的Parcelable方式. 本文介紹SerializableParcelable的使用方式, 含有Demo.

本文源碼的GitHub下載地址


Serializable

序列化User類, 實現Serializable接口即可. 注意serialVersionUID用於輔助序列化與反序列化, 只有相同時, 纔會正常進行. 如不指定, 則系統會自動生成Hash值, 修改類代碼, 可能會導致無法反序列化, 所以強制指定.

public class UserSerializable implements Serializable {
    // 標準序列ID, 用於判斷版本
    private static final long serialVersionUID = 1L;

    public int userId;
    public String userName;
    public boolean isMale;

    public UserSerializable(int userId, String userName, boolean isMale) {
        this.userId = userId;
        this.userName = userName;
        this.isMale = isMale;
    }
}

序列化對象, 使用ObjectOutputStream存儲已經序列化的對象數據, 通過writeObject寫入對象.

public void serialIn(View view) {
    Context context = view.getContext();
    File cache = new File(context.getCacheDir(), "cache.txt");
    try {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(cache));
        UserSerializable user = new UserSerializable(0, "Spike", false);
        out.writeObject(user);
        out.close();
        Toast.makeText(context, "序列化成功", Toast.LENGTH_SHORT).show();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

緩存文件位置: new File(context.getCacheDir(), "cache.txt").

反序列對象, 使用ObjectInputStream反序列化對象, 通過readObject讀取對象的持久化信息.

public void serialOut(View view) {
    Context context = view.getContext();
    File cache = new File(context.getCacheDir(), "cache.txt");
    UserSerializable newUser = null;
    try {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(cache));
        newUser = (UserSerializable) in.readObject();
        in.close();
    } catch (Exception e) {
        e.printStackTrace();
        Toast.makeText(context, "請先序列化", Toast.LENGTH_SHORT).show();

    }
    if (newUser != null) {
        String content = "序號: " + newUser.userId
                + ", 姓名: " + newUser.userName
                + ", 性別: " + (newUser.isMale ? "男" : "女");
        mSerialTvContent.setText(content);
    } else {
        mSerialTvContent.setText("無數據");
    }
}

Parcelable

Android推薦的序列化對象方式. 實現Parcelable接口, writeToParcel寫入對象的變量, UserParcelable提供解析對象方式. CREATOR是創建序列化對象的匿名類, 必須實現, 包含創建單個對象與數組的方式. describeContents只有在含有文件描述符是返回1, 默認都是返回0, 不需要修改.

public class UserParcelable implements Parcelable {
    public int userId;
    public String userName;
    public boolean isMale;
    public BookParcelable book;

    public UserParcelable(int userId, String userName, boolean isMale, String bookName) {
        this.userId = userId;
        this.userName = userName;
        this.isMale = isMale;
        this.book = new BookParcelable(bookName);
    }

    @Override public int describeContents() {
        return 0;
    }

    @Override public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(userId);
        dest.writeString(userName);
        dest.writeInt(isMale ? 1 : 0);
        dest.writeParcelable(book, 0);
    }

    public static final Parcelable.Creator<UserParcelable> CREATOR = new Parcelable.Creator<UserParcelable>() {
        @Override public UserParcelable createFromParcel(Parcel source) {
            return new UserParcelable(source);
        }

        @Override public UserParcelable[] newArray(int size) {
            return new UserParcelable[size];
        }
    };

    private UserParcelable(Parcel source) {
        userId = source.readInt();
        userName = source.readString();
        isMale = source.readInt() == 1;
        book = source.readParcelable(Thread.currentThread().getContextClassLoader());
    }
}

使用Intent傳遞對象數據, 編號0, 姓名Spike, 性別女, 喜歡書籍三國演義.

public void parcelSend(View view) {
    Intent intent = new Intent(PASS_PARCEL_FILTER);
    intent.putExtra(PARCEL_EXTRA, new UserParcelable(0, "Spike", false, "三國演義"));
    mLBM.sendBroadcast(intent);
}

解析廣播Intent的數據, 使用getParcelableExtra方法即可.

private BroadcastReceiver mParcelReceiver = new BroadcastReceiver() {
    @Override public void onReceive(Context context, Intent intent) {
        UserParcelable newUser = intent.getParcelableExtra(PARCEL_EXTRA);
        if (newUser != null) {
            String content = "序號: " + newUser.userId
                    + ", 姓名: " + newUser.userName
                    + ", 性別: " + (newUser.isMale ? "男" : "女")
                    + ", 書: " + newUser.book.bookName;
            Toast.makeText(context, content, Toast.LENGTH_SHORT).show();
            mParcelTvContent.setText(content);
        }
    }
};

效果

動畫

Serializable序列化需要大量的IO操作, Parcelable序列化雖然使用複雜, 但是效率很高, 是Android開發的首選. Parcelable主要應用於內存序列化, 如Intent廣播等.

OK, that’s all! Enjoy it!


最初發布地址:
http://www.wangchenlong.org/2016/05/07/1605/072-serial-object/
歡迎Follow我的GitHub, 關注我的簡書, CSDN, 掘金.
我已委託“維權騎士”爲我的文章進行維權行動. 未經授權, 禁止轉載, 授權或合作請留言.

發佈了721 篇原創文章 · 獲贊 3023 · 訪問量 409萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章