android Activity之間資料傳遞 Parcelable和Serializable介面的使用

來源:互聯網
上載者:User

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)基礎資料型別 (Elementary Data Type),自身可以
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的,把枚舉當做類來看就行了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.