`
chjmars
  • 浏览: 77288 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

阅读更多

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. */
	@Override
	public 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() {

		@Override
		public 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() {

		@Override
		public 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);
		}
	};

	@Override
	protected 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());
				}
			}
		}
	}

	@Override
	public 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 implements
		OnClickListener {

	private Button setSub2XML;
	private TextView mTextView;
	private MyParcel myColor;
	
	private Drawable defDrawable;
	

	/** Called when the activity is first created. */
	@Override
	protected 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());
			}
		}
	}

	@Override
	protected void onStart() {
		super.onStart();
	}

	@Override
	protected void onRestart() {
		super.onRestart();
	}

	@Override
	protected void onResume() {
		super.onResume();
	}

	@Override
	protected void onPause() {
		super.onPause();
	}

	@Override
	protected void onStop() {
		super.onStop();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		return super.onTouchEvent(event);
	}

	@Override
	public 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 implements
		OnClickListener {

	private Button setMainXML;
	private TextView mTextView;
	private BinderMyParcel myColor;

	private Drawable defDrawable;

	/** Called when the activity is first created. */
	@Override
	protected 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());
			}
		}
	}

	@Override
	public 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();
	}

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public 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;
	}

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeValue(data);
	}

	public static final Parcelable.Creator<BinderMyParcel> CREATOR = new Creator<BinderMyParcel>() {

		@Override
		public BinderMyParcel[] newArray(int size) {
			return new BinderMyParcel[size];
		}

		@Override
		public 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>
 

 

分享到:
评论

相关推荐

    在Android中通过Intent使用Bundle传递对象的使用方法

    本文将深入探讨如何在Android中通过Intent使用Bundle来传递对象。 首先,我们需要知道的是,由于Java对象不能直接在内存之间传递,因此必须先将其序列化为字节流。Android提供了两种序列化方式:`Serializable` 和 ...

    Android 通过Intent使用Bundle传递对象详细介绍

    使用Intent和Bundle传递对象的步骤如下: 1. 创建对象并序列化: - 对于Serializable对象,直接将其赋值给Bundle的putSerializable方法。 - 对于Parcelable对象,使用Bundle的putParcelable或putParcelableArray...

    Android学习笔记之bundle用法源码

    总结来说,Bundle是Android中传递数据的关键工具,它的使用涵盖了基本类型、Parcelable和Serializable对象。理解其工作原理和源码实现,有助于开发者更高效地在组件间传递数据,同时避免潜在的性能问题。通过深入...

    bundle传递基本数据,Parcelable类型数据,Serializable类型数据

    在Android应用开发中,`Bundle` 是一个非常重要的工具类,它主要用于在不同组件之间(如Activity、Fragment、Intent)传递数据。`Bundle` 实现了`Parcelable`接口,这使得它可以高效地存储和恢复数据。本篇将详细...

    Android 不同Activity间数据的传递 Bundle对象的应用

    总的来说,Android中不同Activity间的数据传递主要是通过Intent和Bundle进行的,可以传递基本类型的数据以及实现了`Parcelable`或`Serializable`接口的对象。选择哪种方式取决于数据的复杂性和性能需求。`Parcelable...

    Activity之间传递对象的Demo

    在Android中,Activity之间的对象传递主要依赖于Intent、Parcelable接口、Serializable接口以及Bundle。Parcelable接口提供高效的数据传输,适用于频繁的数据交换;Serializable接口使用简单,但效率较低;而Bundle...

    Activity传递对象的3种方法(全)

    在Android开发中,Activity之间的数据传递是至关重要的。本文将详细介绍如何使用三种方法来传递对象:Parcelable、Serializable和Bundle,这些方法适用于不同类型的对象,包括基本类型、字符串、布尔值、数组、...

    Android应用源码之Bundle.zip

    在Android中,如果要将复杂对象(如自定义类实例)放入`Bundle`,对象需要实现`Parcelable`接口。`Parcelable`是Android平台提供的一种高效的数据序列化方式,它比`Serializable`更快,更适合用于内存和Intent传输。...

    Android应用源码之Bundle1_Bundle.zip

    在Android应用开发中,`Bundle` 是一个至关重要的类,用于在组件之间传递数据。它是一个键值对的集合,可以包含任何可序列化的对象,如字符串、整型、浮点型、布尔值以及更复杂的数据结构。在这个“Android应用源码...

    android messager parcelable数据对象传递demo

    `Messenger`是Android系统提供的一种轻量级的IPC机制,而`Parcelable`则是一种高效的数据序列化方式,用于在进程间传递复杂数据对象。 `Messenger`主要用于在两个不同时运行的Android组件之间,如服务和服务、服务...

    eclipse 下的android Activity值传递

    总之,Eclipse下的Android Activity值传递主要依赖Intent和其附加的extras,可以通过基本类型、Parcelable对象、Serializable对象或Bundle进行数据传输。理解这些机制对于构建功能丰富的Android应用至关重要。在实际...

    Android通过Intent传递数据

    在Android应用开发中,Intent是一种强大的机制,用于在组件之间传递信息和启动操作。它扮演着应用程序内部通信的重要角色,特别是在活动(Activity)之间。"Android通过Intent传递数据"这一主题,涵盖了Intent的基本...

    Android使用AIDL完成自定义对象的远程传递示例

    本示例主要探讨如何通过AIDL实现自定义对象的远程传递,这在多进程协作或服务通信中非常常见。 首先,我们需要了解AIDL的基本概念。AIDL文件是一种接口定义文件,它允许我们声明方法签名,这些方法将在服务和客户端...

    【Intent传递】对象、数组

    本DEMO主要讲解如何通过Intent传递对象和数组,这些都是Android开发中的基础知识,对于理解应用程序间的数据通信至关重要。 一、Intent的基本使用 Intent对象是用来表示一个操作的意图,它可以携带少量的数据。在...

    Android中为应用添加多个Activity并实现参数传递案例

    对于Parcelable对象,我们需要在对象类中实现Parcelable接口,并提供写入和读取的实现。例如,我们有一个名为`User`的Parcelable类: ```java public class User implements Parcelable { String name; int age; ...

    android序列化实现

    实现Parcelable接口,需要重写`writeToParcel()`和`describeContents()`方法来完成对象到Parcel的写入和读取操作。这种方式的优点在于它的序列化和反序列化速度非常快,内存占用少,非常适合用于Activity之间或者...

    android参数传递

    首先,Android中最常用的数据传递方式是通过Intent对象。Intent不仅用于启动另一个Activity,还可以承载数据。当你从一个Activity(我们称其为源Activity)启动另一个Activity(目标Activity)时,可以在Intent中...

    诠释Android中序列化的原理与机制

    接下来,我们讨论Parcelable,这是Android特有的序列化机制,主要用于内存中的对象传输,例如在Activity之间传递数据或者保存到Bundle中。相比于Serializable,Parcelable提供了更高的性能和更低的内存消耗。实现...

    AIDL传递自定义对象

    `Parcelable`是Android系统提供的一个高效的数据序列化方式,适用于内存中的对象传输,如Intent或Binder。以下是`Person`类的一个示例: ```java public class Person implements Parcelable { public String name...

Global site tag (gtag.js) - Google Analytics