Android序列化之Parcel

来源:互联网 发布:黑色沙漠男法捏脸数据 编辑:程序博客网 时间:2024/05/23 02:06

序列化方法

在Android系统中关于序列化的方法一般有两种,分别是实现Serializable接口和Parcelable接口,其中Serializable接口是来自Java中的序列化接口,而Parcelable是Android自带的序列化接口。
上述的两种序列化接口都有各自不同的优缺点,我们在实际使用时需根据不同情况而定。

  • Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC,而相比之下Parcelable的性能更高(毕竟是Android自带的),所以当在使用内存时(如:序列化对象在网络中传递对象或序列化在进程间传递对象),更推荐使用Parcelable接口。
  • 但Parcelable有个明显的缺点:不能使用在要将数据存储在磁盘上的情况(如:永久性保存对象,保存对象的字节序列到本地文件中),因为Parcel本质上为了更好的实现对象在IPC间传递,并不是一个通用的序列化机制,当改变任何Parcel中数据的底层实现都可能导致之前的数据不可读取,所以此时还是建议使用Serializable 。

实现Parcelable接口主要有以下几步:
1)implements Parcelable。
2)重写writeToParcel方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从Parcel容器获取数据。
3)重写describeContents方法,内容接口描述,默认返回0即可。
4)实例化静态内部对象CREATOR实现接口Parcelable.Creator 。

下面以一个例子说明:
MainActivity中启动OtherActivity,并将一个对象传过去,这个时候我们就需要对该类实现序列化

package com.test.parcel;import android.os.Parcel;import android.os.Parcelable;import android.util.Log;public class StudentInfo implements Parcelable {      public static final String TAG = "MyParcel";    private String name;      private int age;      private StudentInfo(){    }    public StudentInfo(String name, int age){        Log.i(TAG, "StudentInfo construction");        this.name = name;        this.age = age;    }    public String toString(){        return "name: " + name + ", age:" + age;    }    @Override      public int describeContents() {          // 默认返回0就可以了          Log.i(TAG, "describeContents()");        return 0;      }      @Override      public void writeToParcel(Parcel dest, int flags) {          // 写数据的操作          dest.writeString(name);          dest.writeInt(age);          Log.i(TAG, "writeToParcel()");    }      public static final Parcelable.Creator<StudentInfo> CREATOR = new Creator<StudentInfo>() {          @Override          public StudentInfo[] newArray(int size) {              // TODO Auto-generated method stub              return new StudentInfo[size];          }          @Override          public StudentInfo createFromParcel(Parcel source) {              // 读数据,生成一个新对象,注意顺序跟写的顺序必须一致              StudentInfo stu = new StudentInfo();              stu.name = source.readString();              stu.age = source.readInt();              Log.i(TAG, "Parcelable.Creator createFromParcel()");            return stu;          }      };  }  

我们在MainActivity中创建对象,通过Intent将该对象传给OtherActivity

package com.test.parcel;import java.util.ArrayList;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;public class MainActivity extends Activity implements View.OnClickListener{    private ArrayList<StudentInfo> list;      private Button btn;      @Override      protected void onCreate(Bundle savedInstanceState) {        // TODO Auto-generated method stub          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_main);         btn = (Button) findViewById(R.id.btn);          btn.setOnClickListener(this);          list = getData();      }    private ArrayList<StudentInfo> getData() {          ArrayList<StudentInfo> list = new ArrayList<StudentInfo>();          StudentInfo stu1 = new StudentInfo("scott", 23);          StudentInfo stu2 = new StudentInfo("zhangsan", 18);          StudentInfo stu3 = new StudentInfo("lishi", 20);          list.add(stu1);          list.add(stu2);          list.add(stu3);          return list;      }      @Override      public void onClick(View v) {          // TODO Auto-generated method stub          switch (v.getId()) {          case R.id.btn:              Intent intent = new Intent(this, OtherActivity.class);            Log.i(StudentInfo.TAG, "intent putExtra()");            //若只想传一个对象,则直接调用putExtra(String name, Parcelable value)这个方法即可            //注意这里传的是List,但是该list容器的对象实现了序列化接口,下面这两种调用方法都可以            //intent.putExtra("students", list);              intent.putParcelableArrayListExtra("students", list);            startActivity(intent);              break;          default:              break;          }      }  }

另一个Activity读取数据,生产新对象

package com.test.parcel;import java.util.ArrayList;import android.app.Activity;import android.os.Bundle;public class OtherActivity extends Activity {      private ArrayList<StudentInfo> list;      @Override      protected void onCreate(Bundle savedInstanceState) {          // TODO Auto-generated method stub          super.onCreate(savedInstanceState);          setContentView(R.layout.activity_other);          list = getIntent().getParcelableArrayListExtra("students");          Iterator<StudentInfo> iter = list.iterator();        while(iter.hasNext()){            StudentInfo st = iter.next();            Log.i(StudentInfo.TAG, st.toString());        }    }  }  

当执行putExtra()方法的时候,系统会自动调用Parcelable接口的writeToParcel()方法将数据写入内存中,这就是Android中的序列化。当程序执行 getIntent().getParcelableArrayListExtra(“students”)方法的时候,系统会调用CREATOR对象中的createFromParcel()方法,将序列化到内存的数据反序列化成对象。其实 createFromParcel(Parcel source) 方法的形参source和Parcelable中writeToParcel(Parcel dest, int flags)方法的形参dest是同一个对象。
运行的LOG信息如下:

I/MyParcel( 1268): StudentInfo constructionI/MyParcel( 1268): StudentInfo constructionI/MyParcel( 1268): StudentInfo constructionI/MyParcel( 1268): intent putExtra()I/MyParcel( 1268): writeToParcel()I/MyParcel( 1268): writeToParcel()I/MyParcel( 1268): writeToParcel()I/MyParcel( 1268): Parcelable.Creator createFromParcel()I/MyParcel( 1268): Parcelable.Creator createFromParcel()I/MyParcel( 1268): Parcelable.Creator createFromParcel()I/MyParcel( 1268): name: scott, age:23I/MyParcel( 1268): name: zhangsan, age:18I/MyParcel( 1268): name: lishi, age:20
0 0
原创粉丝点击