Android 序列化的存储和读取总结及简单使用

Android 序列化的存储和读取总结及简单使用,第1张

概述       Android序列化1.序列化的目的 (1).永久的保存对象数据(将对象数据保存在文件当中,或者是磁盘中

       AndroID 序列化

1.序列化的目的

  (1).永久的保存对象数据(将对象数据保存在文件当中,或者是磁盘中

  (2).通过序列化 *** 作将对象数据在网络上进行传输(由于网络传输是以字节流的方式对数据进行传输的.因此序列化的目的是将对象数据转换成字节流的形式)

  (3).将对象数据在进程之间进行传递(Activity之间传递对象数据时,需要在当前的Activity中对对象数据进行序列化 *** 作.在另一个Activity中需要进行反序列化 *** 作讲数据取出)

  (4).Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长(即每个对象都在JVM中)但在现实应用中,就可能要停止JVM运行,但有要保存某些指定的对象,并在将来重新读取被保存的对象。这是Java对象序列化就能够实现该功能。(可选择入数据库、或文件的形式保存)

  (5).序列化对象的时候只是针对变量进行序列化,不针对方法进行序列化.

  (6).在Intent之间,基本的数据类型直接进行相关传递即可,但是一旦数据类型比较复杂的时候,就需要进行序列化 *** 作了.

       AndroID中序列化的实现有两种方式:Serializable接口和Parcelable接口,本文对这两种方式进行简单的总结和使用。

一.相关概念

(一)序列化的原因(序列化能实现的效果)

1.永久性保存对象,保存对象的字节序列到本地文件中;

2.对象在网络中传递;3.对象在IPC间传递。

(二)序列化的方法

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

1.当需要内存较多时使用Parcelable接口。

       Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC,而相比之下 Parcelable的性能更高(毕竟是AndroID自带的),所以当在使用内存时(如:序列化对象在网络中传递对象或序列化在进程间传递对象),更推荐使用Parcelable接口。

2.当需要本地存储时,使用Serializable 接口。

       但Parcelable有个明显的缺点:不能能使用在要将数据存储在磁盘上的情况(如:永久性保 存对象,保存对象的字节序列到本地文件中),因为Parcel本质上为了更好的实现对象在 IPC间传递,并不是一个通用的序列化机制,当改变任何Parcel中数据的底层实现都可能导致之前的数据不可读取,所以此时还是建议使用Serializable 。

二.Serializable接口的使用

       Serializable的接口实现很简单,只需让需要序列化的类继承Serializable即可,系统会自动将其序列化。存储时使用fileOutputStream构造一个ObjectOutputStream,使用writeObject 存储对象。读取时使用fileinputStream构造一个ObjectinputStream,使用readobject读取对象。

(一)布局文件activity_main.xml的设计

<linearLayout   xmlns:androID="http://schemas.androID.com/apk/res/androID"  androID:layout_wIDth="match_parent"  androID:layout_height="match_parent"  androID:orIEntation="vertical"   >  <EditText     androID:layout_wIDth="match_parent"    androID:layout_height="wrap_content"    androID:ID="@+ID/main_et_name"    androID:hint="你的用户名"    />    <EditText     androID:layout_wIDth="match_parent"    androID:layout_height="wrap_content"    androID:ID="@+ID/main_et_password"    androID:hint="你的密码"    />     <EditText     androID:layout_wIDth="match_parent"    androID:layout_height="wrap_content"    androID:ID="@+ID/main_et_age"    androID:hint="你的年龄"    />  <button    androID:onClick="save"    androID:layout_wIDth="wrap_content"    androID:layout_height="wrap_content"    androID:text="保存数据" />   <button    androID:onClick="read"    androID:layout_wIDth="wrap_content"    androID:layout_height="wrap_content"    androID:text="读取数据" />   <TextVIEw     androID:layout_wIDth="match_parent"    androID:layout_height="wrap_content"    androID:text="数据"    androID:ID="@+ID/main_tv"    /></linearLayout>

       界面设计:通过几个输入框输入数据,两个按钮一个保存数据一个读取数据,读取的数据显示在一个文本框下。

(二)创建一个属性类继承Serializable

package com.example.lesson18_serializable;import java.io.Serializable;/** *属性类,用来存储数据,继承接口Serializable,但是什么方法都不用重写! */public class People implements Serializable{  //定义基本信息  String name;  String password;  int age;  //无参构造方法  public People() {    super();  }  //有参构造方法,方便数据写入  public People(String name,String password,int age) {    super();    this.name = name;    this.password = password;    this.age = age;  }  //重写toString方法,方便显示  @OverrIDe  public String toString() {    return "People [name=" + name + ",password=" + password + ",age="        + age ;  }}

(三)主方法的类

package com.example.lesson18_serializable;import java.io.file;import java.io.fileinputStream;import java.io.fileOutputStream;import java.io.IOException;import java.io.ObjectinputStream;import java.io.ObjectOutputStream;import androID.app.Activity;import androID.os.Bundle;import androID.os.Environment;import androID.util.Log;import androID.vIEw.VIEw;import androID.Widget.EditText;import androID.Widget.TextVIEw;public class MainActivity extends Activity {  //保存文件的路径  String path=Environment.getExternalStorageDirectory().getabsolutePath()+"/people.txt";  //定义布局内的控件  EditText edit_name;  EditText edit_password;  EditText edit_age;  TextVIEw text;  @OverrIDe  protected voID onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentVIEw(R.layout.activity_main);    //实例化布局控件    edit_name=(EditText) findVIEwByID(R.ID.main_et_name);    edit_password=(EditText) findVIEwByID(R.ID.main_et_password);    edit_age=(EditText) findVIEwByID(R.ID.main_et_age);    text=(TextVIEw) findVIEwByID(R.ID.main_tv);  }  //保存数据  public voID save(VIEw vIEw){        ObjectOutputStream fos=null;    try {      //如果文件不存在就创建文件      file file=new file(path);      //file.createNewfile();      //获取输出流      //这里如果文件不存在会创建文件,这是写文件和读文件不同的地方      fos=new ObjectOutputStream(new fileOutputStream(file));      //获取输入框内的文件进行写入      String name=edit_name.getText().toString();      String password=edit_password.getText().toString();      int age=Integer.parseInt(edit_age.getText().toString());      People people=new People(name,password,age);      //这里不能再用普通的write的方法了      //要使用writeObject      fos.writeObject(people);;    } catch (Exception e) {      e.printstacktrace();    }finally{      try {        if (fos!=null) {          fos.close();        }      } catch (IOException e) {      }    }  }  //读取数据  public voID read(VIEw vIEw){    ObjectinputStream ois=null;    try {      Log.e("TAG",new file(path).getabsolutePath()+"<---");      //获取输入流      ois=new ObjectinputStream(new fileinputStream(new file(path)));      //获取文件中的数据      Object people=ois.readobject();      //把数据显示在TextVIEw中       text.setText(people.toString());    } catch (Exception e) {      e.printstacktrace();    }finally{      try {        if (ois!=null) {          ois.close();        }      } catch (IOException e) {        e.printstacktrace();      }    }  }}

这里使用但是外部存储的方式来存储数据,需要添加权限:

<uses-permission androID:name="androID.permission.WRITE_EXTERNAL_STORAGE"/>

程序运行后的界面:

输入对应的信息,点击保存,再点击读取显示的结果:

其中这里的数据是保存再本地文件中的,下次不用写入数据,可以直接读取上次写入的文件。

三.Parcelable接口的使用

       使用的方法过程要麻烦一些!

实现Parcelable接口主要可以分为一下几步:

1.让属性类Model实现Parcelable接口2.重写writetoParcel方法,将你的对象序列化为一个Parcel对象,

即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从Parcel容器获取数据。 这里的文件的写入方法非常重要。

3.重写describeContents方法,内容接口描述,默认返回0即可。 这个方法基本没有用!4.实例化静态内部对象CREATOR实现接口Parcelable.Creator,并重写读取的抽象方法。

       这里的读取的方法也是很重要的,必须和写的时候的顺序是一致的。这里的CREATOR接口对象的名字是固定的,如果改成其他名字底层会识别不到这个接口!

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

       这里设计程序从一个页面跳转到另一个页面,并把对象的数据传递过去。

(一)设计属性类继承Parcelable接口

package com.example.lesson18_parcalable;import androID.os.Parcel;import androID.os.Parcelable;/** *属性类,继承Parcelable *实现两个方法,在其中一个方法内实现对象写入的 *** 作 *创建一个接口类CREATOR,重写读取对象的方法 */public class User implements Parcelable{  //User的各种数据的定义  String name;  String password;  int age;  double money;  boolean isadmin;  public User(){}  //写一个构造方法来方便写入数据  public User(String name,int age,double money,boolean isadmin) {    super();    this.name = name;    this.password = password;    this.age = age;    this.money = money;    this.isadmin = isadmin;  }  @OverrIDe  // 这个方法没什么用  public int describeContents() {    return 0;  }  @OverrIDe  // 写数据的底层实现   public voID writetoParcel(Parcel arg0,int arg1) {     arg0.writeString(name);     arg0.writeString(password);     arg0.writeInt(age);     arg0.writeDouble(money);     //把布尔类型的数据做处理,true1,false0     arg0.writeInt(isadmin?1:0);  }  //实例化静态内部对象CREATOR实现接口,CREATOR名字不能改变,否则会报错  public static Creator CREATOR=new Creator<User>() {    @OverrIDe    // 读书数据的底层实现,要和写入的数据的顺序保持一致    public User createFromParcel(Parcel arg0) {      User user=new User();      user.name=arg0.readString();      user.password=arg0.readString();      user.age=arg0.readInt();      user.money=arg0.readDouble();      //布尔类型的数据要处理      user.isadmin=arg0.readInt()==1?true:false;      return user;    }    @OverrIDe    public User[] newArray(int arg0) {       //返回      return new User[arg0];    }  };  //从toString方法  @OverrIDe  public String toString() {    return "User [name=" + name + ",age=" + age        + ",money=" + money + ",isadmin=" + isadmin + "]";  }}

(二)主方法的类的设计

package com.example.lesson18_parcalable;import androID.app.Activity;import androID.content.Intent;import androID.os.Bundle;import androID.vIEw.VIEw;import androID.vIEw.VIEw.OnClickListener;import androID.Widget.button;public class MainActivity extends Activity {  @OverrIDe  protected voID onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);     button button=new button(this);    button.setText("跳转到B页面");    setContentVIEw(button);    button.setonClickListener(new OnClickListener() {            @OverrIDe      public voID onClick(VIEw arg0) {         //跳转到另一个页面,对象的数据也要传递过去        Intent intent=new Intent(MainActivity.this,OtherActivity.class);        //定义数据        User user=new User("liwenzhi","123456",22,1000000,true);        //把数据放到Intent对象里面        intent.putExtra("user",user);        //实现页面跳转        startActivity(intent);      }    });  }}

        上面这个类也是很简单的。设计一个按钮监听跳转到另一个页面。

(三)另一个页面的设计

package com.example.lesson18_parcalable;import androID.app.Activity;import androID.os.Bundle;import androID.Widget.TextVIEw;public class OtherActivity extends Activity{  @OverrIDe  protected voID onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    TextVIEw textVIEw=new TextVIEw(this);    textVIEw.setTextSize(30);    //获取传递过来的数据    User user=getIntent().getParcelableExtra("user");    textVIEw.setText(user.toString());       setContentVIEw(textVIEw);  }}

       上面的页面也是比较简单的,接收从上一个页面传递过来的对象,然后显示在一个TextVIEw。

程序运行后的显示界面:

点击大按钮后,显示的界面:

上面的数据的写死的,其实也是可以向第一个程序那样使用几个输入框来确定数据的。

       对比这两个接口实现的方法和效果: 

       对于第一个程序使用Serializable实现了数据的传递,并且数据是保存在本地的,即使是程序被卸载了,其他程序只要是文件路径正确,也可以访问保存的文件的数据,也是可以用来做进程间的通信的,但是这样需要消耗一些内存。  

     对比第二个程序使用Parcalable实现了数据的传递,这里的数据是不能保存到本地的,占用的内存较少,比较适合用于进程间的数据传递。
对于应用方面:网络信息传递和进程间数据传递使用Parcalable实现了数据的传递的方式是比较多一点的。 

       对于这两种数据传递的信息大小一般不能是很大的数据。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

总结

以上是内存溢出为你收集整理的Android 序列化的存储和读取总结及简单使用全部内容,希望文章能够帮你解决Android 序列化的存储和读取总结及简单使用所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1147538.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存