Android中的Parcel机制 实现Bundle传递对象

来源:互联网 发布:青少年行知实践园地图 编辑:程序博客网 时间:2024/06/06 01:33

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一个新对象。

Mainactivity代码  收藏代码
  1. package com.parcel.main;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.graphics.Color;  
  6. import android.graphics.drawable.Drawable;  
  7. import android.os.Bundle;  
  8. import android.view.MotionEvent;  
  9. import android.view.View;  
  10. import android.view.View.OnClickListener;  
  11. import android.widget.Button;  
  12. import android.widget.TextView;  
  13.   
  14. public class MyTestParcelActivity extends Activity {  
  15.   
  16.     public final static int Sub_Main = 1;  
  17.     public final static int Sub_2_Main = 2;  
  18.   
  19.     private Button setSubMain;  
  20.     private Button setSub2Main;  
  21.     private TextView mTextView;  
  22.   
  23.     private Drawable defDrawable;  
  24.     private MyParcel mMyParcel = new MyParcel();  
  25.     private BinderMyParcel mBinderMyParcel = new BinderMyParcel();  
  26.   
  27.     /** Called when the activity is first created. */  
  28.     @Override  
  29.     public void onCreate(Bundle savedInstanceState) {  
  30.         super.onCreate(savedInstanceState);  
  31.         setContentView(R.layout.main);  
  32.   
  33.         initComponent();  
  34.     }  
  35.   
  36.     private void initComponent() {  
  37.         setSubMain = (Button) findViewById(R.id.btn01);  
  38.         if (setSubMain != null) {  
  39.             setSubMain.setOnClickListener(setSubMainXML);  
  40.         }  
  41.   
  42.         setSub2Main = (Button) findViewById(R.id.btn04);  
  43.         if (setSub2Main != null) {  
  44.             setSub2Main.setOnClickListener(setSub2MainXML);  
  45.         }  
  46.   
  47.         mTextView = (TextView) findViewById(R.id.main_tv);  
  48.         defDrawable = mTextView.getBackground();  
  49.     }  
  50.   
  51.     private View.OnClickListener setSubMainXML = new OnClickListener() {  
  52.   
  53.         @Override  
  54.         public void onClick(View v) {  
  55.             Intent mIntent = new Intent();  
  56.             if (mMyParcel != null) {  
  57.                 mMyParcel.setColor(Color.RED);  
  58.                 mIntent.putExtra("MyColor", mMyParcel);  
  59.             }  
  60.             mIntent.setClass(MyTestParcelActivity.this,  
  61.                     SubMyTestParcelActivity.class);  
  62.   
  63.             mTextView.setBackgroundDrawable(defDrawable);  
  64.   
  65.             startActivityForResult(mIntent, Sub_Main);  
  66.         }  
  67.     };  
  68.     private View.OnClickListener setSub2MainXML = new OnClickListener() {  
  69.   
  70.         @Override  
  71.         public void onClick(View v) {  
  72.             Intent intent = new Intent();  
  73.             if (mBinderMyParcel != null) {  
  74.                 mBinderMyParcel.setColor(Color.MAGENTA);  
  75.                 intent.putExtra("BinderMyColor", mBinderMyParcel);  
  76.             }  
  77.             intent.setClass(MyTestParcelActivity.this,  
  78.                     Sub2MyTestParcelActivity.class);  
  79.   
  80.             mTextView.setBackgroundDrawable(defDrawable);  
  81.   
  82.             startActivityForResult(intent, Sub_2_Main);  
  83.         }  
  84.     };  
  85.   
  86.     @Override  
  87.     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  88.         super.onActivityResult(requestCode, resultCode, data);  
  89.         if (resultCode == RESULT_OK) {  
  90.             if (requestCode == Sub_Main) {  
  91.                 if (data.hasExtra("MyColor")) {  
  92.                     /**  
  93.                      * color=data.getParcelableExtra("MyColor"),  
  94.                      * 这说明反序列化后是一个新的MyColor对象  
  95.                      *   
  96.                      * 如果数据本身是IBinder类型,那么反序列化的结果就是原对象,而不是新建的对象  
  97.                      */  
  98.                     mMyParcel = data.getParcelableExtra("MyColor");  
  99.                     ((TextView) findViewById(R.id.main_tv))  
  100.                             .setTextColor(mMyParcel.getColor());  
  101.                 }  
  102.             } else if (requestCode == Sub_2_Main) {  
  103.                 if (data.hasExtra("BinderMyColor")) {  
  104.                     ((TextView) findViewById(R.id.main_tv))  
  105.                             .setBackgroundColor(mBinderMyParcel.getColor());  
  106.                 }  
  107.             }  
  108.         }  
  109.     }  
  110.   
  111.     @Override  
  112.     public boolean onTouchEvent(MotionEvent event) {  
  113.         return super.onTouchEvent(event);  
  114.     }  
  115.   
  116. }  
 
使用非binder类型代码  收藏代码
  1. package com.parcel.main;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.graphics.Color;  
  6. import android.graphics.drawable.Drawable;  
  7. import android.os.Bundle;  
  8. import android.view.MotionEvent;  
  9. import android.view.View;  
  10. import android.view.View.OnClickListener;  
  11. import android.widget.Button;  
  12. import android.widget.TextView;  
  13.   
  14. public class SubMyTestParcelActivity extends Activity implements  
  15.         OnClickListener {  
  16.   
  17.     private Button setSub2XML;  
  18.     private TextView mTextView;  
  19.     private MyParcel myColor;  
  20.       
  21.     private Drawable defDrawable;  
  22.       
  23.   
  24.     /** Called when the activity is first created. */  
  25.     @Override  
  26.     protected void onCreate(Bundle savedInstanceState) {  
  27.         super.onCreate(savedInstanceState);  
  28.   
  29.         setContentView(R.layout.submain);  
  30.   
  31.         setSub2XML = (Button) findViewById(R.id.btn02);  
  32.         setSub2XML.setOnClickListener(this);  
  33.   
  34.         mTextView = (TextView)findViewById(R.id.sub_tv);  
  35.         defDrawable = mTextView.getBackground();  
  36.           
  37.         Intent intent = getIntent();  
  38.         if (intent != null) {  
  39.             if (intent.hasExtra("MyColor")) {  
  40.                 myColor = intent.getParcelableExtra("MyColor");  
  41.                 mTextView.setBackgroundColor(myColor.getColor());  
  42.             }  
  43.         }  
  44.     }  
  45.   
  46.     @Override  
  47.     protected void onStart() {  
  48.         super.onStart();  
  49.     }  
  50.   
  51.     @Override  
  52.     protected void onRestart() {  
  53.         super.onRestart();  
  54.     }  
  55.   
  56.     @Override  
  57.     protected void onResume() {  
  58.         super.onResume();  
  59.     }  
  60.   
  61.     @Override  
  62.     protected void onPause() {  
  63.         super.onPause();  
  64.     }  
  65.   
  66.     @Override  
  67.     protected void onStop() {  
  68.         super.onStop();  
  69.     }  
  70.   
  71.     @Override  
  72.     protected void onDestroy() {  
  73.         super.onDestroy();  
  74.     }  
  75.   
  76.     @Override  
  77.     public boolean onTouchEvent(MotionEvent event) {  
  78.         return super.onTouchEvent(event);  
  79.     }  
  80.   
  81.     @Override  
  82.     public void onClick(View v) {  
  83.         switch (v.getId()) {  
  84.         case R.id.btn02:  
  85.             Intent mIntent = new Intent(getApplicationContext(),  
  86.                     Sub2MyTestParcelActivity.class);  
  87.             if (myColor != null) {  
  88.                 myColor.setColor(Color.GREEN);  
  89.                 mIntent.putExtra("MyColor", myColor);  
  90.             }  
  91.   
  92.             mTextView.setBackgroundDrawable(defDrawable);  
  93.             setResult(RESULT_OK, mIntent);  
  94.             finish();  
  95.             break;  
  96.   
  97.         default:  
  98.             break;  
  99.         }  
  100.     }  
  101.   
  102. }  
 
使用binder类型代码  收藏代码
  1. package com.parcel.main;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.graphics.Color;  
  6. import android.graphics.drawable.Drawable;  
  7. import android.os.Bundle;  
  8. import android.view.View;  
  9. import android.view.View.OnClickListener;  
  10. import android.widget.Button;  
  11. import android.widget.TextView;  
  12.   
  13. public class Sub2MyTestParcelActivity extends Activity implements  
  14.         OnClickListener {  
  15.   
  16.     private Button setMainXML;  
  17.     private TextView mTextView;  
  18.     private BinderMyParcel myColor;  
  19.   
  20.     private Drawable defDrawable;  
  21.   
  22.     /** Called when the activity is first created. */  
  23.     @Override  
  24.     protected void onCreate(Bundle savedInstanceState) {  
  25.         super.onCreate(savedInstanceState);  
  26.   
  27.         setContentView(R.layout.sub2main);  
  28.   
  29.         setMainXML = (Button) findViewById(R.id.btn03);  
  30.         setMainXML.setOnClickListener(this);  
  31.   
  32.         mTextView = (TextView) findViewById(R.id.sub_tv);  
  33.         defDrawable = mTextView.getBackground();  
  34.   
  35.         Intent intent = getIntent();  
  36.         if (intent != null) {  
  37.             if (intent.hasExtra("BinderMyColor")) {  
  38.                 myColor = intent.getParcelableExtra("BinderMyColor");  
  39.                 mTextView.setBackgroundColor(myColor.getColor());  
  40.             }  
  41.         }  
  42.     }  
  43.   
  44.     @Override  
  45.     public void onClick(View v) {  
  46.         switch (v.getId()) {  
  47.         case R.id.btn03:  
  48.             Intent mIntent = new Intent(getApplicationContext(),  
  49.                     MyTestParcelActivity.class);  
  50.             if (myColor != null) {  
  51.                 myColor.setColor(Color.WHITE);  
  52.                 mIntent.putExtra("BinderMyColor", myColor);  
  53.             }  
  54.   
  55.             mTextView.setBackgroundDrawable(defDrawable);  
  56.             setResult(RESULT_OK, mIntent);  
  57.             finish();  
  58.             break;  
  59.   
  60.         default:  
  61.             break;  
  62.         }  
  63.     }  
  64.   
  65. }  

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

Java代码  收藏代码
  1. package com.parcel.main;  
  2.   
  3. import android.graphics.Color;  
  4. import android.os.Parcel;  
  5. import android.os.Parcelable;  
  6.   
  7. public class MyParcel implements Parcelable {  
  8.     private int color = Color.BLACK;  
  9.   
  10.     public int getColor() {  
  11.         return color;  
  12.     }  
  13.   
  14.     public void setColor(int color) {  
  15.         this.color = color;  
  16.     }  
  17.   
  18.     public MyParcel() {  
  19.         color = Color.BLACK;  
  20.     }  
  21.   
  22.     public MyParcel(Parcel in) {  
  23.         color = in.readInt();  
  24.     }  
  25.   
  26.     @Override  
  27.     public int describeContents() {  
  28.         return 0;  
  29.     }  
  30.   
  31.     @Override  
  32.     public void writeToParcel(Parcel dest, int flags) {  
  33.         dest.writeInt(color);  
  34.     }  
  35.   
  36.     public static final Parcelable.Creator<MyParcel> CREATOR = new Parcelable.Creator<MyParcel>() {  
  37.   
  38.         public MyParcel createFromParcel(Parcel in) {  
  39.             return new MyParcel(in);  
  40.         }  
  41.   
  42.         public MyParcel[] newArray(int size) {  
  43.             return new MyParcel[size];  
  44.         }  
  45.     };  
  46.   
  47. }  

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

Java代码  收藏代码
  1. package com.parcel.main;  
  2.   
  3. import android.os.Binder;  
  4.   
  5. public class BinderData extends Binder {  
  6.   
  7.     public int color;  
  8.   
  9. }  

 其次再实现Parcelable接口:

Java代码  收藏代码
  1. package com.parcel.main;  
  2.   
  3. import android.graphics.Color;  
  4. import android.os.Parcel;  
  5. import android.os.Parcelable;  
  6.   
  7. public class BinderMyParcel implements Parcelable {  
  8.   
  9.     private BinderData data = new BinderData();  
  10.   
  11.     public BinderMyParcel() {  
  12.         data.color = Color.BLUE;  
  13.     }  
  14.   
  15.     public BinderMyParcel(Parcel in) {  
  16.         data = (BinderData) in.readValue(BinderData.class.getClassLoader());  
  17.     }  
  18.   
  19.     public void setColor(int color) {  
  20.         data.color = color;  
  21.     }  
  22.   
  23.     public int getColor() {  
  24.         return data.color;  
  25.     }  
  26.   
  27.     @Override  
  28.     public int describeContents() {  
  29.         return 0;  
  30.     }  
  31.   
  32.     @Override  
  33.     public void writeToParcel(Parcel dest, int flags) {  
  34.         dest.writeValue(data);  
  35.     }  
  36.   
  37.     public static final Parcelable.Creator<BinderMyParcel> CREATOR = new Creator<BinderMyParcel>() {  
  38.   
  39.         @Override  
  40.         public BinderMyParcel[] newArray(int size) {  
  41.             return new BinderMyParcel[size];  
  42.         }  
  43.   
  44.         @Override  
  45.         public BinderMyParcel createFromParcel(Parcel source) {  
  46.             return new BinderMyParcel(source);  
  47.         }  
  48.     };  
  49. }  

三个XML:

1代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical" android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent">  
  5.     <TextView android:id="@+id/main_tv" android:layout_width="fill_parent"  
  6.         android:layout_height="wrap_content" android:text="@string/main_activity" />  
  7.     <LinearLayout android:orientation="horizontal"  
  8.         android:layout_width="wrap_content" android:layout_height="wrap_content">  
  9.         <Button android:text="SetSubMainXML" android:id="@+id/btn01"  
  10.             android:layout_width="wrap_content" android:layout_height="wrap_content" />  
  11.         <Button android:id="@+id/btn04" android:layout_height="wrap_content"  
  12.             android:layout_width="wrap_content" android:text="SetSub2MainXML" />  
  13.     </LinearLayout>  
  14.   
  15. </LinearLayout>  
 
2代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical" android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent">  
  5.     <TextView android:id="@+id/sub_tv" android:layout_width="fill_parent"  
  6.         android:layout_height="wrap_content" android:text="@string/sub_activity" />  
  7.     <Button android:text="setMainXML" android:id="@+id/btn02"  
  8.         android:layout_width="wrap_content" android:layout_height="wrap_content" />  
  9. </LinearLayout>  
 
3代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical" android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent">  
  5.     <TextView android:id="@+id/sub_tv" android:layout_width="fill_parent"  
  6.         android:layout_height="wrap_content" android:text="@string/sub2_activity" />  
  7.     <Button android:text="setMainXML" android:id="@+id/btn03"  
  8.         android:layout_width="wrap_content" android:layout_height="wrap_content" />  
  9. </LinearLayout>  
 
0 0