Adnroid Intent或持久化存储处理复杂对象

BeaYMB 9年前
   <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>