Adnroid Intent或持久化存储处理复杂对象
BeaYMB
8年前
<p>在进程或页面通信时需要使用Intent传递数据; 在对象持久化时需要存储数据. 对于复杂的对象, 进行序列化才可传递或存储, 可以使用<code>Java的Serializable</code>方式或<code>Android的Parcelable</code>方式. 本文介绍<strong>Serializable</strong>和<strong>Parcelable</strong>的使用方式.</p> <p><img src="https://simg.open-open.com/show/f6177d0fa75bde7f7352867ccfb2497d.jpg"></p> <p>Intent<br> ![Uploading device-2016-05-07-120335_116576.gif . . .]</p> <p>本文源码的GitHub<a href="/misc/goto?guid=4959672536974819500">下载地址</a></p> <h2>Serializable</h2> <p>序列化<strong>User</strong>类, 实现<code>Serializable</code>接口即可. 注意<strong>serialVersionUID</strong>用于辅助序列化与反序列化, 只有相同时, 才会正常进行. 如不指定, 则系统会自动生成Hash值, 修改类代码, 可能会导致无法反序列化, 所以强制指定.</p> <pre> <code class="language-java">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; } }</code></pre> <p>序列化对象, 使用<code>ObjectOutputStream</code>存储已经序列化的对象数据, 通过<code>writeObject</code>写入对象.</p> <pre> <code class="language-java">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(); } }</code></pre> <blockquote> <p>缓存文件位置: <code>new File(context.getCacheDir(), "cache.txt")</code>.</p> </blockquote> <p>反序列对象, 使用<code>ObjectInputStream</code>反序列化对象, 通过<code>readObject</code>读取对象的持久化信息.</p> <pre> <code class="language-java">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("无数据"); } }</code></pre> <h2>Parcelable</h2> <p>Android推荐的序列化对象方式. 实现<code>Parcelable</code>接口, <code>writeToParcel</code>写入对象的变量, <code>UserParcelable</code>提供解析对象方式. <code>CREATOR</code>是创建序列化对象的匿名类, 必须实现, 包含创建单个对象与数组的方式. <code>describeContents</code>只有在含有文件描述符是返回1, 默认都是返回0, 不需要修改.</p> <pre> <code class="language-java">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()); } }</code></pre> <p>使用Intent传递对象数据, 编号0, 姓名Spike, 性别女, 喜欢书籍三国演义.</p> <pre> <code class="language-java">public void parcelSend(View view) { Intent intent = new Intent(PASS_PARCEL_FILTER); intent.putExtra(PARCEL_EXTRA, new UserParcelable(0, "Spike", false, "三国演义")); mLBM.sendBroadcast(intent); }</code></pre> <p>解析广播Intent的数据, 使用<code>getParcelableExtra</code>方法即可.</p> <pre> <code class="language-java">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); } } };</code></pre> <p>效果</p> <p><img src="https://simg.open-open.com/show/3cdde8ddcaa62d03ed93c03d688e9d5a.gif" alt="Adnroid Intent或持久化存储处理复杂对象" width="320" height="565"></p> <p>动画</p> <p>Serializable序列化需要大量的IO操作, Parcelable序列化虽然使用复杂, 但是效率很高, 是Android开发的首选. Parcelable主要应用于内存序列化, 如Intent广播等.</p> <p>OK, that's all! Enjoy it!</p> <p>文/<a href="/misc/goto?guid=4959672537061666462">SpikeKing</a>(简书)<br> </p>