美文网首页AndroidAndroid开发经验谈Android开发
Android 序列化-Serializable接口和Parce

Android 序列化-Serializable接口和Parce

作者: 芒果味的你呀 | 来源:发表于2017-09-01 20:43 被阅读101次

    什么是序列化?

    • 序列化(将对象转换为二进制序列的过程)
    • 反序列化(将二进制转化成对象)

    为什么要序列化?

    • 在底层,系统不认识对象,只认识字节序列。
    • 实现序列化的目的主要有三个:
    1. 是跨进程通信
    2. 是对象可以在activity之间和网络之间传递
    3. 是实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里)

    如何序列化?

    android实现序列化有两种方式:一是实现Serializable接口、二是实现Parcelable接口(android原生)

    使用之实现Serializable接口

    原理:Serializabale接口是一个空接口,实际上只提供标记的功能,标记实现了该接口的对象是可以进行序列化的,而具体的序列化与反序列化操作是由ObjectOutputStream和ObjectInputStream完成的。内部采用java的反射机制,在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,所以相比之下消耗一定的性能,开销比较大。

    使用示例

    public class User implements Serializable
    
    {
       private static final long serialVersionUID = 5459584623637090823L;
       private String username;
       private int age;
    
       public User(String username, int age) {
           this.username = username;
           this.age = age;
       }
    
       public int getAge() {
           return age;
       }
    
       public void setAge(int age) {
           this.age = age;
       }
    
       public String getUsername() {
    
           return username;
       }
    
       public void setUsername(String username) {
           this.username = username;
       }
    }
    
    
    public class MainActivity extends AppCompatActivity {
       String path=Environment.getExternalStorageDirectory().getAbsoluteFile()+"/"+"user.dat";
       private TextView textView;
       @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_main);
           textView= (TextView) findViewById(R.id.tv);
           //利用serializable,将对象保存到本地
           storageSerializable();
           //利用serializable,读取本地的serializable数据
           getSerializable();
       }
    
       private void getSerializable() {
           FileInputStream fis=null;
           ObjectInputStream ois=null;
           File file=new File(path);
           try{
               if (file.exists()){
                   fis=new FileInputStream(file);
                   ois=new ObjectInputStream(fis);
                   User user= (User) ois.readObject();
                   textView.setText(user.getAge()+user.getUsername());
                   //Log.i("user","name:"+user2.getUsername()+"age:"+user2.getAge());
               }
           }catch (Exception e){
               e.printStackTrace();
           }
    
       }
    
       private void storageSerializable() {
           User user=new User("李哈哈",21);
           FileOutputStream fos=null;
           ObjectOutputStream oos=null;
    
           try{
               File file=new File(path);
               if (!file.getParentFile().exists()){
                   file.getParentFile().mkdirs();//创建目录
               }
    
               if (!file.exists()){
                   file.createNewFile();
               }
               fos=new FileOutputStream(file);
               oos=new ObjectOutputStream(fos);
               oos.writeObject(user);
           }catch (Exception e){
               e.printStackTrace();
           }finally {
               try {
                   //在这里做资源的关闭
                   if (oos!=null){
                       oos.close();
                   }
                   if (fos!=null){
                       fos.close();
                   }
    
               }catch (Exception e){
                   e.printStackTrace();
               }
    
           }
       }
    }
    
    

    使用之实现Parcelable接口

    原理:Parcelable是Android提供的接口,它主要是通过writeToParcel(),将需要持久化的字段保存到一个Parcel对象里面,然后通过CREATOR从Parcel对象中,取出相应的字段,完成对象的恢复过程。这整个过程均由用户自己控制,可以自定义保存和恢复的字段,所以存储代价小很多。

    使用步骤:

    1.实现Parcelable接口

    2.重写writeToPaecle,将你的对象序列化为一个Parcel对象

    3.重写describeContents方法

    4.实例化静态内部对象CREATOR实现接口Parcelable.Creator 。

    注意:若将Parcel看成是一个流,则先通过writeToParcel把对象写到流里面,再通过createFromParcel从流里读取对象,因此类实现的写入顺序和读出顺序必须一致。

    使用示例

    public class Person implements Parcelable {
       private String username;
       private int age;
    
       public Person(int age) {
           this.age = age;
       }
    
       public Person(String username) {
           this.username = username;
       }
    
       protected Person(Parcel in) {
           username=in.readString();
           age=in.readInt();
       }
       ///实例化静态内部对象CREATOR实现接口,CREATOR名字不能改变,否则会报错
       public static final Creator<Person> CREATOR = new Creator<Person>() {
           // 读书数据的底层实现,要和写入的数据的顺序保持一致
           @Override
           public Person createFromParcel(Parcel in) {
               return new Person(in);
           }
    
           @Override
           public Person[] newArray(int size) {
               return new Person[size];
           }
       };
    
       @Override
       public int describeContents() {
           return 0;
       }
    
       @Override
       public void writeToParcel(Parcel parcel, int i) {
           parcel.writeString(username);
           parcel.writeInt(age);
       }
    
       public Person(String username, int age) {
           this.username = username;
           this.age = age;
       }
    
       @Override
       public String toString() {
           return "name:"+username+"age:"+age;
       }
    }
    
    
    //在mainavtivity中写一个button
    button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Intent intent=new Intent(MainActivity.this,OtherActivity.class);
                    Person person=new Person("李哈哈",21);
                    intent.putExtra("person",person);
                    startActivity(intent);
                }
            });
    
    //在othereactivity中接受数据并显示出来
    public  class OtherActivity  extends Activity{
        private TextView textView;
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.other_activity);
            textView=findViewById(R.id.textview);
            //获取传递过来的数据
            Person person=getIntent().getParcelableExtra("person");
            textView.setText(person.toString());
        }
    }
    

    Serializable和Parcelable的对比

    1.Parcelable接口是android官方提供,Serializable接口是java的

    2.Parcelable接口底层是内存的copy,而Serializable底层是文件IO操作,同时会使用到反射技术,所以效率上,Parcelable要远高于Serializable;

    3.Parcelable具有更好地可控性,我们可以自己控制需要保存和恢复的字段,同时节省空间开销。而Serializable,我们不能自己控制,而是将整个对象进行序列化。

    4.在读写数据的时候,Parcelable是在内存中直接进行读写,而Serializable是通过使用IO流的形式将数据读写入在硬盘上。所以Serializable保存的数据在本地,可数据持久化。Parcelable内存开销比较小。

    相关文章

      网友评论

      本文标题:Android 序列化-Serializable接口和Parce

      本文链接:https://www.haomeiwen.com/subject/hgwkjxtx.html