Android:Intent传递数据的几种类型和源码实现
2015-08-08 14:40
507 查看
[java] view
plaincopy
public class Intent implements Parcelable, Cloneable { //... private String mAction;
private Uri mData;
private String mType;
private String mPackage;
private ComponentName mComponent;
private int mFlags;
private HashSet<String> mCategories;
private Bundle mExtras;
private Rect mSourceBounds;
Intent也是继承了Parcelable的接口。
个人理解,Intent应该只是一个数据参数的载体,真正将两个Acitivity/Service通信起来的是Binder接口(C/S架构)。
第一类:简单或基本数据类型
[java] view
plaincopy
Intent putExtra(String name, int[] value)
Intent putExtra(String name, float value)
Intent putExtra(String name, byte[] value)
Intent putExtra(String name, long[] value)
Intent putExtra(String name, float[] value)
Intent putExtra(String name, long value)
Intent putExtra(String name, String[] value)
Intent putExtra(String name, boolean value)
Intent putExtra(String name, boolean[] value)
Intent putExtra(String name, short value)
Intent putExtra(String name, double value)
Intent putExtra(String name, short[] value)
Intent putExtra(String name, String value)
Intent putExtra(String name, byte value)
Intent putExtra(String name, char[] value)
Intent putExtra(String name, CharSequence[] value)
本质上仍然是通过一个Bundle(private Bundle mExtras;)来实现:
[java] view
plaincopy
public Intent putExtra(String name, long value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putLong(name, value);
return this;
}
第二类:传递一个Bundle
[java] view
plaincopy
public Intent putExtra(String name, Bundle value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putBundle(name, value);
return this;
}
第三类:传递Serializable对象
[java] view
plaincopy
public Intent putExtra(String name, Serializable value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putSerializable(name, value);
return this;
}
第四类:Parcelable对象
[java] view
plaincopy
public Intent putExtra(String name, Parcelable value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putParcelable(name, value);
return this;
}
public Intent putExtra(String name, Parcelable[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putParcelableArray(name, value);
return this;
}
第五类:Intent
[java] view
plaincopy
public Intent putExtras(Intent src) {
if (src.mExtras != null) {
if (mExtras == null) {
mExtras = new Bundle(src.mExtras);
} else {
mExtras.putAll(src.mExtras);
}
}
return this;
}
归根结底都是通过Bundle来实现数据封装。而Bundle则是通过Map的数据结构来存储数据。
mMap = new HashMap<String, Object>();
mParcelledData
两者同时只有一个有效。
一旦unparcel以后,mParcelledData
的数据将被填充到mMap中,同时值为null。在writeToParcel和readFromParcel中则直接使用mParcelledData.此时一般通过IBinder关联两个进程的通信。
关于Bundle则是实现了Parcelable接口的类,通过上面提到的HashMap和一个Parcel来存储数据。
[java] view
plaincopy
public final class Bundle implements Parcelable, Cloneable {
private static final String LOG_TAG = "Bundle";
public static final Bundle EMPTY;
static {
EMPTY = new Bundle();
EMPTY.mMap = Collections.unmodifiableMap(new HashMap<String, Object>());
}
// Invariant - exactly one of mMap / mParcelledData will be null
// (except inside a call to unparcel)
/* package */ Map<String, Object> mMap = null;
/*
* If mParcelledData is non-null, then mMap will be null and the
* data are stored as a Parcel containing a Bundle. When the data
* are unparcelled, mParcelledData willbe set to null.
*/
/* package */ Parcel mParcelledData = null;
[java] view
plaincopy
public void putFloat(String key, float value) {
unparcel();//首先解析出mParcelledData到mMap
mMap.put(key, value);
}
/* package */ synchronized void unparcel() {
if (mParcelledData == null) {
return;
}
int N = mParcelledData.readInt();
if (N < 0) {
return;
}
if (mMap == null) {
mMap = new HashMap<String, Object>();
}
mParcelledData.readMapInternal(mMap, N, mClassLoader);
mParcelledData.recycle();
mParcelledData = null;//回收以后值为null
}
从上面我们可以看出Parcel的写入和读出顺序是一致的。如果元素是list读出时需要先new一个ArrayList传入,否则会报空指针异常。如下:
PS: 在自己使用时,read数据时误将前面int数据当作long读出,结果后面的顺序错乱,报如下异常,当类字段较多时务必保持写入和读取的类型及顺序一致。
4、高级功能上
Serializable序列化不保存静态变量,可以使用Transient关键字对部分字段不进行序列化,也可以覆盖writeObject、readObject方法以实现序列化过程自定义
其他:
android.os.BadParcelableException: ClassNotFoundException
when unmarshalling
参考:
http://developer.android.com/reference/android/os/Parcelable.html
plaincopy
public class Intent implements Parcelable, Cloneable { //... private String mAction;
private Uri mData;
private String mType;
private String mPackage;
private ComponentName mComponent;
private int mFlags;
private HashSet<String> mCategories;
private Bundle mExtras;
private Rect mSourceBounds;
Intent也是继承了Parcelable的接口。
个人理解,Intent应该只是一个数据参数的载体,真正将两个Acitivity/Service通信起来的是Binder接口(C/S架构)。
第一类:简单或基本数据类型
[java] view
plaincopy
Intent putExtra(String name, int[] value)
Intent putExtra(String name, float value)
Intent putExtra(String name, byte[] value)
Intent putExtra(String name, long[] value)
Intent putExtra(String name, float[] value)
Intent putExtra(String name, long value)
Intent putExtra(String name, String[] value)
Intent putExtra(String name, boolean value)
Intent putExtra(String name, boolean[] value)
Intent putExtra(String name, short value)
Intent putExtra(String name, double value)
Intent putExtra(String name, short[] value)
Intent putExtra(String name, String value)
Intent putExtra(String name, byte value)
Intent putExtra(String name, char[] value)
Intent putExtra(String name, CharSequence[] value)
本质上仍然是通过一个Bundle(private Bundle mExtras;)来实现:
[java] view
plaincopy
public Intent putExtra(String name, long value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putLong(name, value);
return this;
}
第二类:传递一个Bundle
[java] view
plaincopy
public Intent putExtra(String name, Bundle value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putBundle(name, value);
return this;
}
第三类:传递Serializable对象
[java] view
plaincopy
public Intent putExtra(String name, Serializable value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putSerializable(name, value);
return this;
}
第四类:Parcelable对象
[java] view
plaincopy
public Intent putExtra(String name, Parcelable value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putParcelable(name, value);
return this;
}
public Intent putExtra(String name, Parcelable[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putParcelableArray(name, value);
return this;
}
第五类:Intent
[java] view
plaincopy
public Intent putExtras(Intent src) {
if (src.mExtras != null) {
if (mExtras == null) {
mExtras = new Bundle(src.mExtras);
} else {
mExtras.putAll(src.mExtras);
}
}
return this;
}
归根结底都是通过Bundle来实现数据封装。而Bundle则是通过Map的数据结构来存储数据。
mMap = new HashMap<String, Object>();
mParcelledData
两者同时只有一个有效。
一旦unparcel以后,mParcelledData
的数据将被填充到mMap中,同时值为null。在writeToParcel和readFromParcel中则直接使用mParcelledData.此时一般通过IBinder关联两个进程的通信。
关于Bundle则是实现了Parcelable接口的类,通过上面提到的HashMap和一个Parcel来存储数据。
[java] view
plaincopy
public final class Bundle implements Parcelable, Cloneable {
private static final String LOG_TAG = "Bundle";
public static final Bundle EMPTY;
static {
EMPTY = new Bundle();
EMPTY.mMap = Collections.unmodifiableMap(new HashMap<String, Object>());
}
// Invariant - exactly one of mMap / mParcelledData will be null
// (except inside a call to unparcel)
/* package */ Map<String, Object> mMap = null;
/*
* If mParcelledData is non-null, then mMap will be null and the
* data are stored as a Parcel containing a Bundle. When the data
* are unparcelled, mParcelledData willbe set to null.
*/
/* package */ Parcel mParcelledData = null;
[java] view
plaincopy
public void putFloat(String key, float value) {
unparcel();//首先解析出mParcelledData到mMap
mMap.put(key, value);
}
/* package */ synchronized void unparcel() {
if (mParcelledData == null) {
return;
}
int N = mParcelledData.readInt();
if (N < 0) {
return;
}
if (mMap == null) {
mMap = new HashMap<String, Object>();
}
mParcelledData.readMapInternal(mMap, N, mClassLoader);
mParcelledData.recycle();
mParcelledData = null;//回收以后值为null
}
从上面我们可以看出Parcel的写入和读出顺序是一致的。如果元素是list读出时需要先new一个ArrayList传入,否则会报空指针异常。如下:
list = new ArrayList<String>(); in.readStringList(list);
PS: 在自己使用时,read数据时误将前面int数据当作long读出,结果后面的顺序错乱,报如下异常,当类字段较多时务必保持写入和读取的类型及顺序一致。
11-21 20:14:10.317: E/AndroidRuntime(21114): Caused by: java.lang.RuntimeException: Parcel android.os.Parcel@4126ed60: Unmarshalling unknown type code 3014773 at offset 164
4、高级功能上
Serializable序列化不保存静态变量,可以使用Transient关键字对部分字段不进行序列化,也可以覆盖writeObject、readObject方法以实现序列化过程自定义
其他:
android.os.BadParcelableException: ClassNotFoundException
when unmarshalling
参考:
http://developer.android.com/reference/android/os/Parcelable.html
相关文章推荐
- android_Color.RGB 颜色之间渐变基本算法
- Android 开发资源
- Android客户端添加正式签名文件的操作说明
- 解决Android系统中CSS设置select高度无效的BUG
- android中的Bitmap
- android animation的简单使用
- Android 之LayoutInflater详解
- (转)Android 操作系统的内存回收机制
- (转)Android系统启动过程
- Android发展_备份短信
- Android加载SD卡图片出现too large to be uploaded into a texture (4128x2322, max=4096x4096)的解决办法
- 浅析Android Context
- 聊天式对话框布局问题match_parent和layout_gravity那些事(android点点滴滴)
- Android之——卸载应用程序
- android学习笔记(4)Intent初级学习
- Android WebView加载html文本时,图片太大不能适配屏幕
- 在Android studio中进行NDK开发
- android内存泄露
- Android-获取全局Context的技巧-android学习之旅(68)
- Android-获取全局Context的技巧-android学习之旅(68)