Android中的Parcel机制
实现了Bundle传递对象
使用Bundle传递对象,首先要将其序列化,但是,在Android中要使用这种传递对象的方式需要用到Android Parcel机制,即,Android实现的轻量级的高效的对象序列化和反序列化机制。

JAVA中的Serialize机制,译成串行化、序列化……,其作用是能将数据对象存入字节流当中,在需要时重新生成对象。主要应用是利用外部存储设备保存对象状态,以及通过网络传输对象等。

Android中的新的序列化机制
在Android系统中,定位为针对内存受限的设备,因此对性能要求更高,另外系统中采用了新的IPC(进程间通信)机制,必然要求使用性能更出色的对象传输方式。在这样的环境下,
Parcel被设计出来,其定位就是轻量级的高效的对象序列化和反序列化机制。
Android中序列化有以下几个特征:
1. 整个读写全是在内存中进行,所以效率比JAVA序列化中使用外部存储器会高很多;
2. 读写时是4字节对齐的
3. 如果预分配的空间不够时,会一次多分配50%;
4. 对于普通数据,使用的是mData内存地址,对于IBinder类型的数据以及FileDescriptor使用的是mObjects内存地址。后者是通过flatten_binder()和unflatten_binder()实现的,目的是反序列化时读出的对象就是原对象而不用重新new一个新对象。

package com.parcel.main;import android.app.Activity;import android.content.Intent;import android.graphics.Color;import android.graphics.drawable.Drawable;import android.os.Bundle;import android.view.MotionEvent;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class MyTestParcelActivity extends Activity {public final static int Sub_Main = 1;public final static int Sub_2_Main = 2;private Button setSubMain;private Button setSub2Main;private TextView mTextView;private Drawable defDrawable;private MyParcel mMyParcel = new MyParcel();private BinderMyParcel mBinderMyParcel = new BinderMyParcel();/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);initComponent();}private void initComponent() {setSubMain = (Button) findViewById(R.id.btn01);if (setSubMain != null) {setSubMain.setOnClickListener(setSubMainXML);}setSub2Main = (Button) findViewById(R.id.btn04);if (setSub2Main != null) {setSub2Main.setOnClickListener(setSub2MainXML);}mTextView = (TextView) findViewById(R.id.main_tv);defDrawable = mTextView.getBackground();}private View.OnClickListener setSubMainXML = new OnClickListener() {@Overridepublic void onClick(View v) {Intent mIntent = new Intent();if (mMyParcel != null) {mMyParcel.setColor(Color.RED);mIntent.putExtra("MyColor", mMyParcel);}mIntent.setClass(MyTestParcelActivity.this,SubMyTestParcelActivity.class);mTextView.setBackgroundDrawable(defDrawable);startActivityForResult(mIntent, Sub_Main);}};private View.OnClickListener setSub2MainXML = new OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent();if (mBinderMyParcel != null) {mBinderMyParcel.setColor(Color.MAGENTA);intent.putExtra("BinderMyColor", mBinderMyParcel);}intent.setClass(MyTestParcelActivity.this,Sub2MyTestParcelActivity.class);mTextView.setBackgroundDrawable(defDrawable);startActivityForResult(intent, Sub_2_Main);}};@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode == RESULT_OK) {if (requestCode == Sub_Main) {if (data.hasExtra("MyColor")) {/** * color=data.getParcelableExtra("MyColor"), * 这说明反序列化后是一个新的MyColor对象 *  * 如果数据本身是IBinder类型,那么反序列化的结果就是原对象,而不是新建的对象 */mMyParcel = data.getParcelableExtra("MyColor");((TextView) findViewById(R.id.main_tv)).setTextColor(mMyParcel.getColor());}} else if (requestCode == Sub_2_Main) {if (data.hasExtra("BinderMyColor")) {((TextView) findViewById(R.id.main_tv)).setBackgroundColor(mBinderMyParcel.getColor());}}}}@Overridepublic boolean onTouchEvent(MotionEvent event) {return super.onTouchEvent(event);}}
package com.parcel.main;import android.app.Activity;import android.content.Intent;import android.graphics.Color;import android.graphics.drawable.Drawable;import android.os.Bundle;import android.view.MotionEvent;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class SubMyTestParcelActivity extends Activity implementsOnClickListener {private Button setSub2XML;private TextView mTextView;private MyParcel myColor;private Drawable defDrawable;/** Called when the activity is first created. */@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.submain);setSub2XML = (Button) findViewById(R.id.btn02);setSub2XML.setOnClickListener(this);mTextView = (TextView)findViewById(R.id.sub_tv);defDrawable = mTextView.getBackground();Intent intent = getIntent();if (intent != null) {if (intent.hasExtra("MyColor")) {myColor = intent.getParcelableExtra("MyColor");mTextView.setBackgroundColor(myColor.getColor());}}}@Overrideprotected void onStart() {super.onStart();}@Overrideprotected void onRestart() {super.onRestart();}@Overrideprotected void onResume() {super.onResume();}@Overrideprotected void onPause() {super.onPause();}@Overrideprotected void onStop() {super.onStop();}@Overrideprotected void onDestroy() {super.onDestroy();}@Overridepublic boolean onTouchEvent(MotionEvent event) {return super.onTouchEvent(event);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn02:Intent mIntent = new Intent(getApplicationContext(),Sub2MyTestParcelActivity.class);if (myColor != null) {myColor.setColor(Color.GREEN);mIntent.putExtra("MyColor", myColor);}mTextView.setBackgroundDrawable(defDrawable);setResult(RESULT_OK, mIntent);finish();break;default:break;}}}
package com.parcel.main;import android.app.Activity;import android.content.Intent;import android.graphics.Color;import android.graphics.drawable.Drawable;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class Sub2MyTestParcelActivity extends Activity implementsOnClickListener {private Button setMainXML;private TextView mTextView;private BinderMyParcel myColor;private Drawable defDrawable;/** Called when the activity is first created. */@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.sub2main);setMainXML = (Button) findViewById(R.id.btn03);setMainXML.setOnClickListener(this);mTextView = (TextView) findViewById(R.id.sub_tv);defDrawable = mTextView.getBackground();Intent intent = getIntent();if (intent != null) {if (intent.hasExtra("BinderMyColor")) {myColor = intent.getParcelableExtra("BinderMyColor");mTextView.setBackgroundColor(myColor.getColor());}}}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btn03:Intent mIntent = new Intent(getApplicationContext(),MyTestParcelActivity.class);if (myColor != null) {myColor.setColor(Color.WHITE);mIntent.putExtra("BinderMyColor", myColor);}mTextView.setBackgroundDrawable(defDrawable);setResult(RESULT_OK, mIntent);finish();break;default:break;}}}

非Binder类型的Parcel,实现Parcelable接口即可:

package com.parcel.main;import android.graphics.Color;import android.os.Parcel;import android.os.Parcelable;public class MyParcel implements Parcelable {private int color = Color.BLACK;public int getColor() {return color;}public void setColor(int color) {this.color = color;}public MyParcel() {color = Color.BLACK;}public MyParcel(Parcel in) {color = in.readInt();}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeInt(color);}public static final Parcelable.Creator<MyParcel> CREATOR = new Parcelable.Creator<MyParcel>() {public MyParcel createFromParcel(Parcel in) {return new MyParcel(in);}public MyParcel[] newArray(int size) {return new MyParcel[size];}};}

对于Binder类型,首先要实现一个Binder接口(其,最主要的区别在于反序列化仍然是原来的对象,而非Binder类型的反序列化并不是原来的对象,所以在MainActivity中的onActivityResult方法中会出现mMyParcel = data.getParcelableExtra("MyColor")的写法):

package com.parcel.main;import android.os.Binder;public class BinderData extends Binder {public int color;}

其次再实现Parcelable接口:

package com.parcel.main;import android.graphics.Color;import android.os.Parcel;import android.os.Parcelable;public class BinderMyParcel implements Parcelable {private BinderData data = new BinderData();public BinderMyParcel() {data.color = Color.BLUE;}public BinderMyParcel(Parcel in) {data = (BinderData) in.readValue(BinderData.class.getClassLoader());}public void setColor(int color) {data.color = color;}public int getColor() {return data.color;}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeValue(data);}public static final Parcelable.Creator<BinderMyParcel> CREATOR = new Creator<BinderMyParcel>() {@Overridepublic BinderMyParcel[] newArray(int size) {return new BinderMyParcel[size];}@Overridepublic BinderMyParcel createFromParcel(Parcel source) {return new BinderMyParcel(source);}};}

三个XML:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="fill_parent"android:layout_height="fill_parent"><TextView android:id="@+id/main_tv" android:layout_width="fill_parent"android:layout_height="wrap_content" android:text="@string/main_activity" /><LinearLayout android:orientation="horizontal"android:layout_width="wrap_content" android:layout_height="wrap_content"><Button android:text="SetSubMainXML" android:id="@+id/btn01"android:layout_width="wrap_content" android:layout_height="wrap_content" /><Button android:id="@+id/btn04" android:layout_height="wrap_content"android:layout_width="wrap_content" android:text="SetSub2MainXML" /></LinearLayout></LinearLayout>
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="fill_parent"android:layout_height="fill_parent"><TextView android:id="@+id/sub_tv" android:layout_width="fill_parent"android:layout_height="wrap_content" android:text="@string/sub_activity" /><Button android:text="setMainXML" android:id="@+id/btn02"android:layout_width="wrap_content" android:layout_height="wrap_content" /></LinearLayout>
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="fill_parent"android:layout_height="fill_parent"><TextView android:id="@+id/sub_tv" android:layout_width="fill_parent"android:layout_height="wrap_content" android:text="@string/sub2_activity" /><Button android:text="setMainXML" android:id="@+id/btn03"android:layout_width="wrap_content" android:layout_height="wrap_content" /></LinearLayout>

更多相关文章

  1. Android事件分发机制 详解攻略
  2. Android夸进程通信机制七:使用 Socket进行进程间通信
  3. android内存处理机制
  4. Android 支持多屏幕机制
  5. Android 分类法:六个类型,八种用户
  6. android消息机制
  7. Android应用程序的类型
  8. Android群英传笔记——第九章:Android系统信息和安全机制
  9. 【整理】Android中EditText中的InputType类型含义与如何定义

随机推荐

  1. 【性能】Android中的内存溢出(Out Of Memo
  2. Android之帧动画与补间动画的使用
  3. android中listview的一些样式设置(关键点
  4. Android中ListView实现子控件点击事件后L
  5. Android:实时改变配置
  6. 关于代码家(干货集中营)共享知识点汇总系
  7. Android(安卓)11:新特性前瞻
  8. [置顶] Android 开发之旅:view的几种布局
  9. 三星首款Android手机上市
  10. Android 在onCreate()方法中获取控件宽高