android提供了一种新的类型:parcel(英文解释:包裹,小包),本类用来封装数据的容器,封装后的数据可以
通过Intent或IPC传递,简单点来说:Parcel就是一个存放读取数据的容器。
Parcelable 接口:它的实例可以从 parcel 中写入和恢复,实现 Parcelable 接口也必须有一个非空的静态字段的类型,该类型实现了 Parcelable.Creator 接口。
下面将用其实现不同组件之间的数据传递,效果如下:
定义一个 MyParcelable 类,实现 Parcelable 接口:
package com.android.datatest;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.HashMap;
public class MyParcelable implements Parcelable {
//定义要被传输的数据
public int mInt;
public String mStr;
public int mImages;
public HashMap<String,String> mMap = new HashMap<String,String>();
public int describeContents() {
// 默认返回 0
return 0;
}
public void writeToParcel(Parcel out, int flags) {
// 将数据到写入 Parcel 中去
out.writeInt(mInt);
out.writeString(mStr);
out.writeInt(mImages);
out.writeMap(mMap);
}
public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
private MyParcelable(Parcel in) {
// 将映射在Parcel对象中的数据还原回来
// 这里顺序一定要和writeToParcel中定义的顺序一致才行!!
mInt = in.readInt();
mStr = in.readString();
mImages = in.readInt();
mMap = in.readHashMap(HashMap.class.getClassLoader());
}
public MyParcelable(){}
}
MainActivity.java :
package com.android.datatest;
import java.util.HashMap;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intentParcelable = new Intent();
MyParcelable mp = new MyParcelable();
// 可以传递数字,字符串,集合,图片等
mp.mInt = 2;
mp.mStr = "字符串";
mp.mImages = R.drawable.ic_launcher;
mp.mMap = new HashMap<String, String>();
mp.mMap.put("key", "value");
intentParcelable.putExtra("Parcelable", mp);
intentParcelable.setClass(MainActivity.this, ParcelableActivity.class);
startActivity(intentParcelable);
}
}
ParcelableActivity.java :
package com.android.datatest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;
public class ParcelableActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
//接收参数
Intent intent = getIntent();
MyParcelable mp = intent.getParcelableExtra("Parcelable");
TextView tv = (TextView)findViewById(R.id.tv);
tv.setText("mInt : " + mp.mInt
+"\r\n mStr : "+mp.mStr
+"\r\n size() : "+mp.mMap.size());
ImageView imageView = (ImageView)findViewById(R.id.imageView);
int data = mp.mImages;
imageView.setImageResource(data);
}
}
second.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/tv"
android:textSize="30sp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="数据传输"/>
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Serializable实现简单,不需要任何额外的序列化操作。而Parcelable实现较为复杂。 Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC,而相比之下Parcelable的性能更高,所以当在使用内存时(如:序列化对象在网络中传递对象或序列化在进程间传递对象),更推荐使用Parcelable接口。 Parcelable有个明显的缺点:不能使用在要将数据存储在磁盘上的情况(如:永久性保存对象,保存对象的字节序列到本地文件中),因为Parcel本质上为了更好的实现对象在IPC间传递,并不是一个通用的序列化机制,当改变任何Parcel中数据的底层实现都可能导致之前的数据不可读取,所以此时还是建议使用Serializable 。