Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android Activity之間數據傳遞 Parcelable和Serializable接口的使用

android Activity之間數據傳遞 Parcelable和Serializable接口的使用

編輯:關於Android編程

Activity之間傳數據時,為了避免麻煩,往往會將一些值封裝成對象,然後將整個對象傳遞過去。傳對象的時候有兩種情況,一種是實現Parcelable接口,一種是實現Serializable接口。
0、解釋兩種接口:
1)實現Serializable接口是JavaSE本身就支持的。
2)Parcelable是Android特有的功能,效率比實現Serializable接口高,像用於Intent數據傳遞也都支持,而且還可以用在進程間通信(IPC),除了基本類型外,只有實現了Parcelable接口的類才能被放入Parcel中。
3)什麼時候使用序列化?
a)當你想把的內存中的對象寫入到硬盤的時候;

b)當你想用套接字在網絡上傳送對象的時候;

c)當你想通過RMI傳輸對象的時候;
再稍微解釋一下:a)比如說你的內存不夠用了,那計算機就要將內存裡面的一部分對象暫時的保存到硬盤中,等到要用的時候再讀入到內存中,硬盤的那部分存儲空間就是所謂的虛擬內存。在比如過你要將某個特定的對象保存到文件中,我隔幾天在把它拿出來用,那麼這時候就要實現Serializable接口;

b)在進行java的Socket編程的時候,你有時候可能要傳輸某一類的對象,那麼也就要實現Serializable接口;最常見的你傳輸一個字符串,它是JDK裡面的類,也實現了Serializable接口,所以可以在網絡上傳輸。

c)如果要通過遠程的方法調用(RMI)去調用一個遠程對象的方法,如在計算機A中調用另一台計算機B的對象的方法,那麼你需要通過JNDI服務獲取計算機B目標對象的引用,將對象從B傳送到A,就需要實現序列化接口。
1、什麼是Parcelable接口呢?
1)Parcelable,定義了將數據寫入Parcel,和從Parcel中讀出的接口。一個實體(用類來表示),如果需要封裝到消息中去,就必須實現這一接口,實現了這一接口,該實體就成為“可打包的”了。
2)Parcelable接口的定義:
public interface Parcelable {
    //內容描述接口,基本不用管
    public int describeContents();
    //寫入接口函數,打包
    public void writeToParcel(Parcel dest, int flags);
     //讀取接口,目的是要從Parcel中構造一個實現了Parcelable的類的實例處理。因為實現類在這裡還是不可知的,所以需要用到模板的方式,繼承類名通過模板參數傳入。
    //為了能夠實現模板參數的傳入,這裡定義Creator嵌入接口,內含兩個接口函數分別返回單個和多個繼承類實例。
    public interface Creator<T> {
        public T createFromParcel(Parcel source);
        public T[] newArray(int size);
 }
}
3)怎麼實現Parcelable接口?
從parcelable接口定義中,我們可以看到,實現parcelable接口,需要我們實現下面幾個方法:
(1.)describeContents方法。內容接口描述,默認返回0就可以;
(2.)writeToParcel 方法。該方法將類的數據寫入外部提供的Parcel中.即打包需要傳遞的數據到Parcel容器保存,以便從parcel容器獲取數據,該方法聲明如下:
writeToParcel (Parcel dest, int flags) 具體參數含義見doc文檔
(3.)靜態的Parcelable.Creator接口,本接口有兩個方法:
createFromParcel(Parcel in)  從Parcel容器中讀取傳遞數據值,封裝成Parcelable對象返回邏輯層。
newArray(int size) 創建一個類型為T,長度為size的數組,僅一句話(return new T[size])即可。方法是供外部類反序列化本類數組使用。
4)代碼實現>
(1.)實現MyParcelable類:
package com.jyxp.my.parcelable;

import java.util.ArrayList;
import java.util.List;

import android.os.Parcel;
import android.os.Parcelable;

public class MyParcelable implements Parcelable {
 
 private int mInteger;
 private MyParcelable2 mParcelable;
 private List<MyParcelable2> myParcelable2s = new ArrayList<MyParcelable2>();
 private MySerializable mMySerializable;
 
 public MyParcelable() {
  // TODO Auto-generated constructor stub
 }
 
 @SuppressWarnings("unchecked")
 public MyParcelable(Parcel in) {
  // TODO Auto-generated constructor stub
  mInteger = in.readInt();
  mParcelable = in.readParcelable(MyParcelable2.class.getClassLoader()); //這個地方的ClassLoader不能為null
  myParcelable2s = in.readArrayList(MyParcelable2.class.getClassLoader());
  mMySerializable = (MySerializable) in.readSerializable();
 }

 public int getmInteger() {
  return mInteger;
 }

 public void setmInteger(int mInteger) {
  this.mInteger = mInteger;
 }

 public MyParcelable2 getmParcelable() {
  return mParcelable;
 }

 public void setmParcelable(MyParcelable2 mParcelable) {
  this.mParcelable = mParcelable;
 }

 public List<MyParcelable2> getMyParcelable2s() {
  return myParcelable2s;
 }

 public void setMyParcelable2s(List<MyParcelable2> myParcelable2s) {
  this.myParcelable2s = myParcelable2s;
 }

 public MySerializable getmMySerializable() {
  return mMySerializable;
 }

 public void setmMySerializable(MySerializable mMySerializable) {
  this.mMySerializable = mMySerializable;
 }

 @Override
 public int describeContents() {
  // TODO Auto-generated method stub
  return 0;
 }

 @Override
 public void writeToParcel(Parcel dest, int flags) {
  // TODO Auto-generated method stub
  dest.writeInt(mInteger);
  dest.writeParcelable(mParcelable, flags);
  dest.writeList(myParcelable2s);
  dest.writeSerializable(mMySerializable);  
 }
   
 public static final Parcelable.Creator<MyParcelable> CREATOR = new Creator<MyParcelable>() {
  
  @Override
  public MyParcelable[] newArray(int size) {
   // TODO Auto-generated method stub
   return new MyParcelable[size];
  }
  
  @Override
  public MyParcelable createFromParcel(Parcel source) {
   // TODO Auto-generated method stub
   return new MyParcelable(source);
  }
 };
}
注意:
1、必須實現Parcelable.Creator接口,並且訪問控制必須是public!!;實現Parcelable.Creator接口對象名必須為CREATOR!!否則在獲取數據的時候,會報錯,如下:android.os.BadParcelableException:
2、在讀取Parcel容器裡的數據時,必須按成員變量聲明的順序讀取數據,不然會出現獲取數據出錯。
3、注意Parcel out和in對應的屬性順序不能錯,否則得不到值;如果想傳遞的值沒有write和read,同樣也是獲取不到值的。
4、實現Parcelable接口我采用的做法是,從android API文檔中找到Parcelable接口,詳見Android 文檔,將demo copy,然後將MyParcelable類名全部替換,再填寫write和read的值。在填寫值的時候上面的代碼給出了一些示例,有時候會出現以下錯誤:
(1、)Caused By:android.os.BadParcelableException: ClassNotFoundException when unmarshalling,原因是ClassLoader設置不對,或者沒有傳入ClassLoader。
(2、)java.lang.RuntimeException: Parcelable encountered IOException writing serializable object,原因是傳遞的Parcelable對象裡面的對象也要Parcelable或者Serializable。
2、什麼是Serializable接口?
1)一個對象序列化的接口,一個類只有實現了Serializable接口,它的對象才是可序列化的。因此如果要序列化某些類的對象,這些類就必須實現Serializable接口。而實際上,Serializable是一個空接口,沒有什麼具體內容,它的目的只是簡單的標識一個類的對象可以被序列化。
2)如何實現Serializable接口?
很簡單,只要implements Serializable接口就可以了
3)代碼實現>
package com.jyxp.my.parcelable;

import java.io.Serializable;

public class MySerializable implements Serializable {
 
 private static final long serialVersionUID = 1L;
 private Double mDouble;
 private Float mFloat;
 
 public MySerializable() {
  // TODO Auto-generated constructor stub
 }

 public Double getmDouble() {
  return mDouble;
 }

 public void setmDouble(Double mDouble) {
  this.mDouble = mDouble;
 }

 public Float getmFloat() {
  return mFloat;
 }

 public void setmFloat(Float mFloat) {
  this.mFloat = mFloat;
 }
}
3、如何實現傳值
1)基本數據類型,自身可以
2)傳遞Serializable對象時,被傳遞的Serializable對象裡面的自定義成員對象(非API中的Serializable對象)也要實現Serializable接口,否則會出現Caused
 by: java.io.NotSerializableException異常。從上面的代碼可以看出,在Parcelable對象中是可以傳遞Serializable對象的,但Serializable對象裡面傳遞的時候可不可以有Parcelable?回答是否定的,一樣會產生java.io.NotSerializableException異常.
3)android api中只能傳遞Parcelable對象的集合,而不能傳遞Serializable對象的集合,也就是只能傳遞ArrayList<Bitmap>,卻不能傳遞ArrayList<Designer>。剛剛開始學android的時候,對象都是被封裝成Serializable,再傳遞,因為Serializable是JAVASE裡面的本地化接口,很熟悉,當時也產生疑問,為什麼會有Parcelable接口,這兩個有什麼區別?到後來,當Serializable不能滿足要求的時候就明白了,android利用Pacelable對自己的東西進行封裝,就像Worker中的Bitmap,在read的時候可以不需要設置ClassLoader。
4)也是可以傳遞枚舉enum的,把枚舉當做類來看就行了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved