Android -- Parcelable 序列化操作数据(上篇)
2016-04-09 15:27
344 查看
http://blog.csdn.net/andyhuabing/article/details/7703401
序列化数据原理:
序列化的过程就是对象写入字节流和从字节流中读取对象。将对象状态转换成字节流之后,可以用java.io包中的各种字节流类将其保存到文件中,管道到另一线程中或通过网络连接将对象数据发送到另一主机。
简单说就是将数据对象存入字节流当中,在需要时重新生成对象。
Android中的序列化机制:
首先android系统利用Binder进行IPC通讯,且定位为针对内存受限的设备,所以则要求使用高效的对象传输方式,因为Parcel应运而生。
代码分析:
frameworks\base\core\java\android\os\Parcel.java
frameworks\base\core\jni\android_util_Binder.cpp JNI函数
以典型代码片段举例:
[java] view
plain copy
print?
<span style="font-size:16px;"> /**
* Write an integer value into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
public final native void writeInt(int val);
/**
* Write a long integer value into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
public final native void writeLong(long val);
/**
* Write a floating point value into the parcel at the current
* dataPosition(), growing dataCapacity() if needed.
*/
public final native void writeFloat(float val);</span>
JNI层实现:
[cpp] view
plain copy
print?
<span style="font-size:16px;">static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val)
{
Parcel* parcel = parcelForJavaObject(env, clazz);
if (parcel != NULL) {
const status_t err = parcel->writeInt32(val);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
}
}
}
static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val)
{
Parcel* parcel = parcelForJavaObject(env, clazz);
if (parcel != NULL) {
const status_t err = parcel->writeInt64(val);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
}
}
}
static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val)
{
Parcel* parcel = parcelForJavaObject(env, clazz);
if (parcel != NULL) {
const status_t err = parcel->writeFloat(val);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
}
}
}</span>
其本质使用 Parcel 对象来完成的,实现代码在:frameworks/base/libs/binder/parcel.cpp
[cpp] view
plain copy
print?
<span style="font-size:16px;"> status_t Parcel::writeInt32(int32_t val)
{
return writeAligned(val);
}
--> 直接利用模块实现
template<class T>
status_t Parcel::writeAligned(T val) {
COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
if ((mDataPos+sizeof(val)) <= mDataCapacity) {
restart_write:
*reinterpret_cast<T*>(mData+mDataPos) = val; // 直接在此将数据写入到内存中
return finishWrite(sizeof(val));
}
status_t err = growData(sizeof(val)); // 数据空间不够的情况下处理
if (err == NO_ERROR) goto restart_write;
return err;
}
status_t Parcel::growData(size_t len)
{
size_t newSize = ((mDataSize+len)*3)/2; // 每次多分配50%的内存空间
return (newSize <= mDataSize)
? (status_t) NO_MEMORY
: continueWrite(newSize);
} </span>
总结:
1、整个读写全是在内存中进行,主要是通过malloc()、realloc()、memcpy()等内存操作进行
2、读写时是PAD_SIZE=4字节对齐, #define PAD_SIZE(s) (((s)+3)&~3)
3、预分配的空间不够时newSize = ((mDataSize+len)*3)/2;会一次多分配50%
4、普通数据,使用的是mData内存地址,对于IBinder类型的数据以及FileDescriptor使用的是mObjects内存地址
举个例子说明一下如何在同一个Activity传递复杂数据类型:
[java] view
plain copy
print?
<span style="font-size:16px;">package com.test.testparcel;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import android.view.KeyEvent;
public class TestParcelActivity extends Activity {
ComplexDataStruct complexData = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_0){
testComplexDS();
}
return super.onKeyUp(keyCode, event);
}
public void testComplexDS(){
complexData = new ComplexDataStruct();
Intent intent=new Intent(TestParcelActivity.this,TestParcelActivity.class);
complexData.a = 10;
complexData.b = 20;
complexData.str1 = " hello...";
complexData.str2 = " world...";
Log.i("","intent.putExtra before");
intent.putExtra("testcomplexData", complexData);
Log.i("","intent.putExtra after");
Log.i("","intent.getParcelableExtra before");
ComplexDataStruct test = (ComplexDataStruct)intent.getParcelableExtra("testcomplexData");
Log.i("","intent.getParcelableExtra after");
Log.i("","a="+test.a);
Log.i("","b="+test.b);
Log.i("","str1="+test.str1);
Log.i("","str2="+test.str2);
}
/* 一个复杂的Parcelable对象传递 */
public class ComplexDataStruct implements Parcelable{
public int a = 0;
public int b = 0;
public String str1 = null;
public String str2 = null;
ComplexDataStruct(){
//TODO
}
public ComplexDataStruct(ComplexDataStruct other) {
this.a = other.a;
this.b = other.b;
this.str1 = other.str1;
this.str2 = other.str2;
}
private ComplexDataStruct(Parcel in) {
Log.e("","readFromParcel is calling...");
readFromParcel(in);
}
public void readFromParcel(Parcel in) {
a = in.readInt();
b = in.readInt();
str1 = in.readString();
str2 = in.readString();
Log.e("","readFromParcel is calling...");
}
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
public void writeToParcel(Parcel arg0, int arg1) {
// TODO Auto-generated method stub
Log.e("","writeToParcel is calling...");
arg0.writeInt(a);
arg0.writeInt(b);
arg0.writeString(str1);
arg0.writeString(str2);
Log.e("","writeToParcel is calling...");
}
/* 内部实现静态CREATOR类 */
public final Parcelable.Creator<ComplexDataStruct> CREATOR =
new Parcelable.Creator<ComplexDataStruct>() {
// 从Parcel中读取数据,返回ComplexDataStruct对象
public ComplexDataStruct createFromParcel(Parcel in) {
Log.e("","createFromParcel is calling...");
return new ComplexDataStruct(in);
}
public ComplexDataStruct[] newArray(int size) {
Log.e("","newArray is calling...");
return new ComplexDataStruct[size]; // 传递数组
}
};
}
}</span>
打印结果:
I/ ( 1324): intent.putExtra before
I/ ( 1324): intent.putExtra after
I/ ( 1324): intent.getParcelableExtra before
I/ ( 1324): intent.getParcelableExtra after
I/ ( 1324): a=10
I/ ( 1324): b=20
I/ ( 1324): str1= hello...
I/ ( 1324): str2= world...
这里利用 intent 发送消息,利用 Bundle 来传递数据,Bundle概念下一篇会讲到。
构建复杂数据类型,需要如下实现:
1、继承自 Parcelable 实现,ex: public class ComplexDataStruct implements Parcelable
2、内部有一个静态的 CREATOR 类 : public static final Parcelable.Creator<ComplexDataStruct> CREATOR
3、实现 writeToParcel 和 readFromParcel 序列化与反序列化函数
4、传递使用 Intent.java 类的函数:putExtra 及 getParcelableXXX函数
序列化数据原理:
序列化的过程就是对象写入字节流和从字节流中读取对象。将对象状态转换成字节流之后,可以用java.io包中的各种字节流类将其保存到文件中,管道到另一线程中或通过网络连接将对象数据发送到另一主机。
简单说就是将数据对象存入字节流当中,在需要时重新生成对象。
Android中的序列化机制:
首先android系统利用Binder进行IPC通讯,且定位为针对内存受限的设备,所以则要求使用高效的对象传输方式,因为Parcel应运而生。
代码分析:
frameworks\base\core\java\android\os\Parcel.java
frameworks\base\core\jni\android_util_Binder.cpp JNI函数
以典型代码片段举例:
[java] view
plain copy
print?
<span style="font-size:16px;"> /**
* Write an integer value into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
public final native void writeInt(int val);
/**
* Write a long integer value into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
public final native void writeLong(long val);
/**
* Write a floating point value into the parcel at the current
* dataPosition(), growing dataCapacity() if needed.
*/
public final native void writeFloat(float val);</span>
JNI层实现:
[cpp] view
plain copy
print?
<span style="font-size:16px;">static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val)
{
Parcel* parcel = parcelForJavaObject(env, clazz);
if (parcel != NULL) {
const status_t err = parcel->writeInt32(val);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
}
}
}
static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val)
{
Parcel* parcel = parcelForJavaObject(env, clazz);
if (parcel != NULL) {
const status_t err = parcel->writeInt64(val);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
}
}
}
static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val)
{
Parcel* parcel = parcelForJavaObject(env, clazz);
if (parcel != NULL) {
const status_t err = parcel->writeFloat(val);
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
}
}
}</span>
其本质使用 Parcel 对象来完成的,实现代码在:frameworks/base/libs/binder/parcel.cpp
[cpp] view
plain copy
print?
<span style="font-size:16px;"> status_t Parcel::writeInt32(int32_t val)
{
return writeAligned(val);
}
--> 直接利用模块实现
template<class T>
status_t Parcel::writeAligned(T val) {
COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
if ((mDataPos+sizeof(val)) <= mDataCapacity) {
restart_write:
*reinterpret_cast<T*>(mData+mDataPos) = val; // 直接在此将数据写入到内存中
return finishWrite(sizeof(val));
}
status_t err = growData(sizeof(val)); // 数据空间不够的情况下处理
if (err == NO_ERROR) goto restart_write;
return err;
}
status_t Parcel::growData(size_t len)
{
size_t newSize = ((mDataSize+len)*3)/2; // 每次多分配50%的内存空间
return (newSize <= mDataSize)
? (status_t) NO_MEMORY
: continueWrite(newSize);
} </span>
总结:
1、整个读写全是在内存中进行,主要是通过malloc()、realloc()、memcpy()等内存操作进行
2、读写时是PAD_SIZE=4字节对齐, #define PAD_SIZE(s) (((s)+3)&~3)
3、预分配的空间不够时newSize = ((mDataSize+len)*3)/2;会一次多分配50%
4、普通数据,使用的是mData内存地址,对于IBinder类型的数据以及FileDescriptor使用的是mObjects内存地址
举个例子说明一下如何在同一个Activity传递复杂数据类型:
[java] view
plain copy
print?
<span style="font-size:16px;">package com.test.testparcel;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import android.view.KeyEvent;
public class TestParcelActivity extends Activity {
ComplexDataStruct complexData = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_0){
testComplexDS();
}
return super.onKeyUp(keyCode, event);
}
public void testComplexDS(){
complexData = new ComplexDataStruct();
Intent intent=new Intent(TestParcelActivity.this,TestParcelActivity.class);
complexData.a = 10;
complexData.b = 20;
complexData.str1 = " hello...";
complexData.str2 = " world...";
Log.i("","intent.putExtra before");
intent.putExtra("testcomplexData", complexData);
Log.i("","intent.putExtra after");
Log.i("","intent.getParcelableExtra before");
ComplexDataStruct test = (ComplexDataStruct)intent.getParcelableExtra("testcomplexData");
Log.i("","intent.getParcelableExtra after");
Log.i("","a="+test.a);
Log.i("","b="+test.b);
Log.i("","str1="+test.str1);
Log.i("","str2="+test.str2);
}
/* 一个复杂的Parcelable对象传递 */
public class ComplexDataStruct implements Parcelable{
public int a = 0;
public int b = 0;
public String str1 = null;
public String str2 = null;
ComplexDataStruct(){
//TODO
}
public ComplexDataStruct(ComplexDataStruct other) {
this.a = other.a;
this.b = other.b;
this.str1 = other.str1;
this.str2 = other.str2;
}
private ComplexDataStruct(Parcel in) {
Log.e("","readFromParcel is calling...");
readFromParcel(in);
}
public void readFromParcel(Parcel in) {
a = in.readInt();
b = in.readInt();
str1 = in.readString();
str2 = in.readString();
Log.e("","readFromParcel is calling...");
}
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
public void writeToParcel(Parcel arg0, int arg1) {
// TODO Auto-generated method stub
Log.e("","writeToParcel is calling...");
arg0.writeInt(a);
arg0.writeInt(b);
arg0.writeString(str1);
arg0.writeString(str2);
Log.e("","writeToParcel is calling...");
}
/* 内部实现静态CREATOR类 */
public final Parcelable.Creator<ComplexDataStruct> CREATOR =
new Parcelable.Creator<ComplexDataStruct>() {
// 从Parcel中读取数据,返回ComplexDataStruct对象
public ComplexDataStruct createFromParcel(Parcel in) {
Log.e("","createFromParcel is calling...");
return new ComplexDataStruct(in);
}
public ComplexDataStruct[] newArray(int size) {
Log.e("","newArray is calling...");
return new ComplexDataStruct[size]; // 传递数组
}
};
}
}</span>
打印结果:
I/ ( 1324): intent.putExtra before
I/ ( 1324): intent.putExtra after
I/ ( 1324): intent.getParcelableExtra before
I/ ( 1324): intent.getParcelableExtra after
I/ ( 1324): a=10
I/ ( 1324): b=20
I/ ( 1324): str1= hello...
I/ ( 1324): str2= world...
这里利用 intent 发送消息,利用 Bundle 来传递数据,Bundle概念下一篇会讲到。
构建复杂数据类型,需要如下实现:
1、继承自 Parcelable 实现,ex: public class ComplexDataStruct implements Parcelable
2、内部有一个静态的 CREATOR 类 : public static final Parcelable.Creator<ComplexDataStruct> CREATOR
3、实现 writeToParcel 和 readFromParcel 序列化与反序列化函数
4、传递使用 Intent.java 类的函数:putExtra 及 getParcelableXXX函数
相关文章推荐
- Android2.3 MediaPlayer系统祥解系列(概述)
- Android学习基本索引(四)——记录,没事自己看
- Android从无知到有知——NO.3
- Android 日志系统logcat内核代码分析
- Android系统开发中LOG的输出与使用
- Android之利用正则表达式校验邮箱、手机号、密码、身份证号码等
- Android——getPreferences()、getSharedPreferences()和getDefaultSharedPreferences()区别
- Android 中文件类型与MIME的匹配表
- Android SDK下载技巧
- Android获取当前连接的wifi名称
- android raw与assets区别
- Android SDK下载技巧
- 浅谈Android管理task方式
- Android随笔
- Android EditText自定义密文符号
- Android任性进程管理之不需要太多的剩余内存
- Android Studio 1.5 配置AndroidAnnotations
- Android中 Paint 字体、粗细等属性的一些设置
- Android:TextInputLayout的简单使用
- 直接拿来用!最火的Android开源项目