如果都了解过Parcel类的实现,那么其基本只序列化基本类型的特性还不能满足我们的需求(事实上android中Binder的IPC通信中,Parcel对象也能传递Parcel对象,现实编程用得极少)。具体的Parcel类这里不做介绍。点击查看Parcel类详解
Serializable和Parcelable在现实中的应用场景,有个网友写得非常nice,强烈推荐大家有空看下。点击查看Serializable和Parcelable你应该懂得的几个应用场景
之前学习java的时候,实现Serializable接口序列化一个对象并通过IO操作就可以保存在本地存储区中。而Parcelable的用法并不是如此。两者间虽然都支持序列化、反序列操作,但是其存储的媒介截然不同。前者一般是通过IO流写入本地硬盘文件中而Parcelable则在写入内存。运行在android手机上的应用追求运行速度更快。假设在同一进程的不同ActivityA和B之前传递一个对象,如果还需要先把A对象写入SD卡,然后B对象再从SD卡读到内存中,那么做了很多功夫。Adnroid提供Parcelable接口直接操作内存中的序列化对象,写入和读取速度明显大于IO操作,因此性能也有所提升。故Android实现序列化对象优先选择“Parcelable”。
如果涉及到网络传输保存数据的,一般还是推荐使用Serializable。
基于上述内容的认知,下面给出Android现实编程的例子:分别用两种序列化方式对具体对象进行序列化,并在不同的Activity中传递。
MainActiviy代码
package com.example.androidtest_parcelable; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private Button ac1,ac2; private Intent intent; private PersonByParcelable p; private PersonBySerializable s; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initListener(); initData(); } public void initView(){ ac1 = (Button)findViewById(R.id.ac1); ac2 = (Button)findViewById(R.id.ac2); } public void initListener(){ ac1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub intent = new Intent(MainActivity.this, ActivityA.class); Bundle b = new Bundle(); b.putParcelable("parcelable", p); intent.putExtras(b); startActivity(intent); } }); ac2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub intent = new Intent(MainActivity.this, ActivityB.class); Bundle b = new Bundle(); b.putSerializable("serializable", s); intent.putExtras(b); startActivity(intent); } }); } public void initData(){ p = new PersonByParcelable(); p.setName("parcelable"); p.setAge(1); p.setAddress("我来自ParsonByParcelable"); s = new PersonBySerializable(); s.setName("serializable"); s.setAge(2); s.setAddress("我来自PersonBySerializable"); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
ActivityA代码,用于显示反序列化Parcelable序列化的对象。
package com.example.androidtest_parcelable; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.widget.TextView; public class ActivityA extends Activity{ private TextView mTextView; private Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ac1); initView(); } public void initView(){ intent = getIntent(); Bundle b = intent.getExtras(); PersonByParcelable p = (PersonByParcelable)b.getParcelable("parcelable"); mTextView = (TextView)findViewById(R.id.mTextView); mTextView.setText("name:"+p.getName()+'\n' +"age:"+p.getAge()+"\n" +"address:"+p.getAddress()); } }
ActivityB代码,用于显示反序列化Serializable序列化的对象。
package com.example.androidtest_parcelable; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.widget.TextView; public class ActivityB extends Activity{ private TextView mTextView; private Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ac2); initView(); } public void initView(){ intent = getIntent(); Bundle b = intent.getExtras(); PersonBySerializable s = (PersonBySerializable) b.getSerializable("serializable"); mTextView = (TextView)findViewById(R.id.mTextView); mTextView.setText("name:"+s.getName()+'\n' +"age:"+s.getAge()+"\n" +"address:"+s.getAddress()); } }
分别对应的xml布局
MainActivity布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:text="welcome to yummlau's bolg" android:textSize="20sp" /> <Button android:id="@+id/ac1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="传递Parcelable对象" /> <Button android:id="@+id/ac2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="传递Serializable对象" /> </LinearLayout>
ActivitA和ActivityB布局(是相同的)
<?xml version="1.0" encoding="UTF-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_marginTop="10dp" android:id="@+id/mTextView" android:layout_width="fill_parent" android:layout_height="100dp" android:textSize="20sp"/> </LinearLayout>
两个Bean类,分别用两种序列化手段
PersonByParcelable类,该类必须实现的的内容有:
1.无参构造器,用于产生类对象
2.有参构造器,用于反序列化后加载对象信息
3.writeToParcel(Parcel dest,int flags),此方法根据自己对象内容,分别按顺序写入dest包中,切记,这里与后面读取的顺序要一直。
4.describeContents(),此方法标志序列化内容,重写默认就可以了。
5.Parcelable.Creator<XXX>,此方法供系统内部存放序列化对象。
</pre></p><p><span style="font-family:SimHei;"></span><pre name="code" class="java" style="font-size:14px;">package com.example.androidtest_parcelable; import android.os.Parcel; import android.os.Parcelable; public class PersonByParcelable implements Parcelable{ private String name; private int age; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public int describeContents() { // TODO Auto-generated method stub return 0; } @Override public void writeToParcel(Parcel dest, int flags) { // TODO Auto-generated method stub dest.writeString(name); dest.writeInt(age); dest.writeString(address); } public static final Parcelable.Creator<PersonByParcelable> CREATOR = new Parcelable.Creator<PersonByParcelable>() { public PersonByParcelable createFromParcel(Parcel in) { return new PersonByParcelable(in); } public PersonByParcelable[] newArray(int size) { return new PersonByParcelable[size]; } }; public PersonByParcelable(){ } public PersonByParcelable(Parcel in){ this.name = in.readString(); this.age = in.readInt(); this.address = in.readString(); } }
PersonBySerializable类,该类必须实现的的内容有:
1.产生序列化ID
注意:该ID分为默认和随机,本demo因为有本地同个进程中实现并且序列化和反序列化都是用同个类,所以我取哪种方式都无所谓。然而如果是序列化和反序列分别在不同端的程序中,那么就应该保持ID的一致性才能正确反序列化对象。详情见开头的应用场景。
package com.example.androidtest_parcelable; import java.io.Serializable; public class PersonBySerializable implements Serializable{ /** * 序列化ID,自动生成 */ private static final long serialVersionUID = 996340687144383140L; private String name; private int age; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
Demo图示
运行后界面
分别点击“传递Parcelable对象”和“传递Serializable对象”
到此基本的传递对象演示完毕,如有错误欢迎指出。