Android中Intent中如何传递对象

Android中Intent中如何传递对象

          

                  1.背景知识: 

  Activity之间通过Intent传递值,支持基本数据类型String对象及它们的数组对象                                                                              ((即byte、byte[]、char、char[]、boolean、boolean[]、short、short[]、int、int[]、

      long、long[]、float、float[]、double、double[]、String、String[] )),

             还有实现Serializable、Parcelable接口的类对象。


所以传递对象的方法.显然

一种是

Serializable---( 

数据放Bundle用intent传  // Bundle.putSerializable(Key,Object);)

另一种是Parcelable---( 传给Service或者Bundle.putParcelable(Key, Object);)的object.

当然这些Object是有一定的条件的,前者是实现了Serializable接口,而后者是实现了Parcelable接口.

(有人不推荐使用Parcelable ,更不推荐用Serialization在Activity间传递数据.那到底用什么呢?后面揭晓,让我们先了解下这两个)

"Android provides two mechanisms that allow you to pass data to another process. 

The first is to pass a bundle to an activity using an intent,

 andthe second is to pass a Parcelable to a service. 

These two mechanisms are not interchangeable and should not be confused. 

That is, the Parcelable is not meant to be passed to an activity. 

If you want to start an activity and pass it some data, use a bundle. 

Parcelable is meant to be used only as part of an AIDL definition."

 


     两者的区别

         1.我们常用的本地的Activity间传递一些数据的办法是用Bundle.   而Parcelable偏向于AIDL.

2.在使用内存的时候,Parcelable 类比Serializable性能高,所以推荐使用Parcelable类。

3. Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。

4. Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下

 

 使用 Parcelable 而不是 serializing的  好处是什么呢?

------即原来谷歌的安卓团队发现 java版的serialization太慢了 ,效率慢的和蜗牛一样快,不能满足安卓进程间通讯的需求. 

详情可以看这个 -----What is the difference between Serializable and Externalizable in Java? 

为此谷歌团队打造了Parcelable.用它来解决问题. 不过你需要自己显示的serialize你的变量

(像下面那断代码那样,系统会自动调用writeToParcel. )

"It turns out that the Android team came to the conclusion that

 the serialization in Java is far too slow to satisfy Android’s  IPC(   interprocess-communication) requirements. 

So the team built the Parcelable solution

The Parcelable approach requires that you explicitly serialize the members of your class,

 but in the end, you get a much faster serialization of your objects.


 参考官方文档地址:developer.android.com/reference/android/os/Parcel.html  


  1. public class Book implements Parcelable {  
  2.     private String bookName;  
  3.     private String author;  
  4.     private int publishTime;  
  5.       
  6.     public String getBookName() {  
  7.         return bookName;  
  8.     }  
  9.     public void setBookName(String bookName) {  
  10.         this.bookName = bookName;  
  11.     }  
  12.     public String getAuthor() {  
  13.         return author;  
  14.     }  
  15.     public void setAuthor(String author) {  
  16.         this.author = author;  
  17.     }  
  18.     public int getPublishTime() {  
  19.         return publishTime;  
  20.     }  
  21.     public void setPublishTime(int publishTime) {  
  22.         this.publishTime = publishTime;  
  23.     }  
  24.       //这里的名字必须是CREATOR
  25.  //android.os.BadParcelableException: Parcelable protocol requires a Parcelable.Creator object called  //CREATOR on class 
  26.     public static final Parcelable.Creator<Book> CREATOR = new Creator<Book>() {  
  27.         public Book createFromParcel(Parcel source) {  
  28.             Book mBook = new Book();  
  29.             mBook.bookName = source.readString();  
  30.             mBook.author = source.readString();  
  31.             mBook.publishTime = source.readInt();  
  32.             return mBook;  
  33.         }  
  34.         public Book[] newArray(int size) {  
  35.             return new Book[size];  
  36.         }  
  37.     };  
  38.       
  39.     public int describeContents() {  
  40.         return 0;  
  41.     }  
  42.     public void writeToParcel(Parcel parcel, int flags) {  
  43.         parcel.writeString(bookName);  
  44.         parcel.writeString(author);  
  45.         parcel.writeInt(publishTime);  
  46.     }  
  47. }  

 

实际的DEMO案例演示:

下载地址 : http://download.csdn.net/detail/f112122/7677937
 

1.MainActivity.class

public class MainActivity extends Activity implements OnClickListener {

	private Button SerializeButton;
	private Button PacelableButton;
	public final static String SER_KEY = "ser_Key";
	public final static String PAR_KEY = "par_Key";

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		SerializeButton = (Button) findViewById(R.id.button1);
		PacelableButton = (Button) findViewById(R.id.button2);
		SerializeButton.setOnClickListener(this);
		PacelableButton.setOnClickListener(this);

	}

	// 铵钮点击事件响应
	public void onClick(View v) {
		if (v == SerializeButton) {

			Intent mIntent = new Intent(this, SerialActivity.class);
			Bundle mBundle = new Bundle();

			Person mPerson = new Person();
			mPerson.setName("Sanjay");
			mPerson.setAge(100);

			mBundle.putSerializable(SER_KEY, mPerson);
			mIntent.putExtras(mBundle);
			startActivity(mIntent);

		} else {

			Intent mIntent = new Intent(this, ParcActivity.class);
			Bundle mBundle = new Bundle();

			Pet mPet = new Pet();
			mPet.setPetName("哈奇士");
			mPet.setAuthor("Sanjay");

			mBundle.putParcelable(PAR_KEY, mPet);
			mIntent.putExtras(mBundle);

			startActivity(mIntent);
		}
	}

}


2.  ParcActivity

public class ParcActivity extends Activity {  
   
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
               
        setContentView(R.layout.activity_parc);
        TextView mPetName_TextView =(TextView)findViewById(R.id.PetName_textView1);
        TextView mAuthorName_TextView =(TextView)findViewById(R.id.textView3);
        
        Pet mPet = (Pet)getIntent().getParcelableExtra(MainActivity.PAR_KEY);<pre name="code" class="java">         mPetName_TextView.setText("Pet name is: " + mPet.getPetName()); 
        mAuthorName_TextView.setText("Author is: " + mPet.getAuthor() ); 
 

 

 //上面这里会调用 .将Implement的接口的writeString数据恢复到圆形.
      /* public static final Parcelable.Creator<Pet> CREATOR = new Creator<Pet>() {
		public Pet createFromParcel(Parcel source) {
			Pet mPet = new Pet();
			mPet.petName = source.readString();
			mPet.author = source.readString();
			return mPet; 
          */                       
} 
}*/
---------------------------------------------------------------------
// 
//记住.下面的readString数据获取方式的顺序.要和writeToParcel的writeString的顺序一样 
  //                    mPet.petName = source.readString();
//			mPet.author = source.readString();


public class SerialActivity extends ActionBarActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_serial);

		TextView mTextView = (TextView) findViewById(R.id.textView1);
		Person mPerson = (Person) getIntent().getSerializableExtra(
				MainActivity.SER_KEY);

		mTextView.setText("名字是:" + mPerson.getName() + "\n" + "年龄是: "
				+ mPerson.getAge());

	}

}

:运行上述工程查看效果图啦:

效果1:首界面:


效果2:点击Serializable按钮                             


效果3:点击Parcelable按钮:

 



 

5:新建两个类一个是Person.java实现Serializable接口,另一个Book.java实现Parcelable接口,代码分别如下:

Person.java:

[java]  view plain copy
  1. package com.tutor.objecttran;  
  2. import java.io.Serializable;  
  3. public class Person implements Serializable {  
  4.     private static final long serialVersionUID = -7060210544600464481L;   
  5.     private String name;  
  6.     private int age;  
  7.     public String getName() {  
  8.         return name;  
  9.     }  
  10.     public void setName(String name) {  
  11.         this.name = name;  
  12.     }  
  13.     public int getAge() {  
  14.         return age;  
  15.     }  
  16.     public void setAge(int age) {  
  17.         this.age = age;  
  18.     }  
  19.       
  20. }  


 Pet类

public class Pet implements Parcelable {
	private String petName;
	private String author;

	public String getPetName() {
		return petName;
	}

	public void setPetName(String Name) {
		this.petName = Name;
	}

	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	public static final Parcelable.Creator<Pet> CREATOR = new Creator<Pet>() {
		public Pet createFromParcel(Parcel source) {
			Pet mPet = new Pet();
			mPet.petName = source.readString();
			mPet.author = source.readString();
			return mPet;
		}

		public Pet[] newArray(int size) {
			return new Pet[size];
		}
	};

	// implement the inherited abstract method describeContents()
	/* 
	 * Describe the kinds of special objects contained in this Parcelable's
	 * marshalled representation. Specified by: describeContents() in Parcelable
	 * 
	 * Returns:a bitmask indicating the set of special object types marshalled
	 * by the Parcelable.
	 */
	public int describeContents() {
		return 0;
	}

	// implement the inherited abstract method writeToParcel(Parcel, int)
	//
	public void writeToParcel(Parcel parcel, int flags) {
		Log.i("writeToParcel", "哎呀,我被调用了");
		parcel.writeString(petName);
		parcel.writeString(author);
	}
}

  虽然parcel 和Parcelable的很高效.但官方文档建议.你不应该用他来做 general-purpose serialization 的存储.因为安卓系统版本不一致.

"Parcel and Parcelable are fantastically quick, but its documentation says you must not use it for general-purpose serialization to storage, since the implementation varies with different versions of Android (i.e. an OS update could break an app which relied on it)."


为此有个大神共享了他自己实现的一个方法.我们可以借鉴下.

   

public interface Packageable {
    public void readFromPackage(PackageInputStream in)  throws IOException ;
    public void writeToPackage(PackageOutputStream out)  throws IOException ; 
}


public final class PackageInputStream {

    private DataInputStream input;

    public PackageInputStream(InputStream in) {
        input = new DataInputStream(new BufferedInputStream(in));
    }

    public void close() throws IOException {
        if (input != null) {
            input.close();
            input = null;
        }       
    }

    // Primitives
    public final int readInt() throws IOException {
        return input.readInt();
    }
    public final long readLong() throws IOException {
        return input.readLong();
    }
    public final long[] readLongArray() throws IOException {
        int c = input.readInt();
        if (c == -1) {
            return null;
        }
        long[] a = new long[c];
        for (int i=0 ; i<c ; i++) {
            a[i] = input.readLong();
        }
        return a;
    }

...

    public final String readString()  throws IOException {
        return input.readUTF();
    }
    public final <T extends Packageable> ArrayList<T> readPackageableList(Class<T> clazz) throws IOException {
        int N = readInt();
        if (N == -1) {
            return null;
        }
        ArrayList<T> list = new ArrayList<T>();
        while (N>0) {
            try {
                T item = (T) clazz.newInstance();
                item.readFromPackage(this);
                list.add(item);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            N--;
        }
        return list;
    }

}



public final class PackageOutputStream {

    private DataOutputStream output;

    public PackageOutputStream(OutputStream out) {
        output = new DataOutputStream(new BufferedOutputStream(out));
    }

    public void close() throws IOException {
        if (output != null) {
            output.close();
            output = null;
        }
    }

    // Primitives
    public final void writeInt(int val) throws IOException {
        output.writeInt(val);
    }
    public final void writeLong(long val) throws IOException {
        output.writeLong(val);
    }
    public final void writeLongArray(long[] val) throws IOException {
        if (val == null) {
            writeInt(-1);
            return;
        }
        writeInt(val.length);
        for (int i=0 ; i<val.length ; i++) {
            output.writeLong(val[i]);
        }
    }

    public final void writeFloat(float val) throws IOException {
        output.writeFloat(val);
    }
    public final void writeDouble(double val) throws IOException {
        output.writeDouble(val);
    }
    public final void writeString(String val) throws IOException {
        if (val == null) {
            output.writeUTF("");
            return;
        }
        output.writeUTF(val);
    }

    public final <T extends Packageable> void writePackageableList(ArrayList<T> val) throws IOException {
        if (val == null) {
            writeInt(-1);
            return;
        }
        int N = val.size();
        int i=0;
        writeInt(N);
        while (i < N) {
            Packageable item = val.get(i);
            item.writeToPackage(this);
            i++;
        }
    }

}


参考数据

http://stackoverflow.com/questions/5550670/benefit-of-using-parcelable-instead-of-serializing-object

一个开源的示例项目: http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking



                                                                文章仓促而成,有什么疑问欢迎大家一起讨论。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值