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

       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, String password, 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 + ", password=" + password + ", 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实现了数据的传递的方式是比较多一点的。

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

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

(0)

相关推荐

  • Android中的序列化浅析

    序列化原因 序列化的原因基本可以归纳为以下三种情况: 1.永久性保存对象,保存对象的字节序列到本地文件中: 2.对象在网络中传递: 3.对象在IPC间传递. 序列化方法 在Android系统中关于序列化的方法一般有两种,分别是实现Serializable接口和Parcelable接口,其中Serializable接口是来自Java中的序列化接口,而Parcelable是Android自带的序列化接口. 上述的两种序列化接口都有各自不同的优缺点,我们在实际使用时需根据不同情况而定. 1.Seria

  • Android xml文件的序列化实现代码

    传统方式: 复制代码 代码如下: public void backSms(View view){  //假设我已经获取到了所有的短信  StringBuilder sb = new StringBuilder();  sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");  sb.append("<smss>");  for(SmsInfo in

  • 解析Android中的Serializable序列化

    1.为何要序列化? -- 把内存中的java对象能够在磁盘上持久保存 -- 通过网络传输对象 -- 通过RMI(Remote Method Invocation 远程过程调用)传输. 通过序列化可以把对象转化为与平台无关的二进制流,在重新使用前进行反序列化,重新转化为java对象. (远程过程调用针对分布式Java应用,对开发人员屏蔽不同JVM和网络连接等细节,是的分布在不同JVM上的对象似乎存在于一个统一的JVM中,能够方便的通讯) 2.如何让Java对象可以被序列化? 在java里只需让目标

  • 很详细的android序列化过程Parcelable

    直接上代码:注释都写的很清楚了. public class Entry implements Parcelable{ public int userID; public String username; public boolean isMale; public Book book;//序列化对象可以嵌套序列化对象,前提是2个类的对象都被序列号过 //几乎所有情况下都返回0,可以不管 @Override public int describeContents() { return 0; } //

  • Android中的Parcelable序列化对象

    今天查阅资料,简单了解了一下Parcelable接口,它是android提供的序列化对象的接口,比java中的 Serializable高效些.通过这个接口序列化对象主要有两步: 1.实现public void writeToParcel(Parcel dest, int flags) {}方法: 2.实例化CREATOR public static final Parcelable.Creator<ParcelableImpl> CREATOR = new Parcelable.Creato

  • Android应用中使用XmlSerializer序列化XML数据的教程

    首先,我们看一下什么是serializer,serializer就是串行化,又名序列化.它可并不只是简单的把对象保存在存储器上,它可以使我们在流中传输对象,使对象变的可以像基本数据一样传递. XmlSerializer是针对XML进行序列化的类库,我们先来看一下里面的常用方法: 基本方法 1.创建一个xml文件的序列化器,返回的是一个Xml的 Serializer 对象. XmlSerializer = Xml.newSerializer(); 2.设置序列化器的输出路径和编码方式 FileOu

  • Android序列化XML数据

    什么是XML?首先我们先了解一下什么是XML.XML,可扩展标记语言 (Extensible Markup Language) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言,这是百度百科的解释.而XML是一种在Internet中传输数据的常见格式,它与HTML一样,都是SGML(标准通用标记语言),无论你是需要通过Internet访问数据,或者发送数据给Web服务,都可能需要用到XML的知识.恰恰Android应用程序

  • Android中Serializable和Parcelable序列化对象详解

    本文详细对Android中Serializable和Parcelable序列化对象进行学习,具体内容如下 学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Parcelable进行序列化操作 5.Parcelable的工作原理 6.相关实例  1.序列化的目的 1).永久的保存对象数据(将对象数据保存在文件当中,或者是磁盘中 2).通过序列化操作将对象数据在网络上进行传输(由于网络传输是以

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

           Android 序列化 1.序列化的目的 (1).永久的保存对象数据(将对象数据保存在文件当中,或者是磁盘中 (2).通过序列化操作将对象数据在网络上进行传输(由于网络传输是以字节流的方式对数据进行传输的.因此序列化的目的是将对象数据转换成字节流的形式) (3).将对象数据在进程之间进行传递(Activity之间传递对象数据时,需要在当前的Activity中对对象数据进行序列化操作.在另一个Activity中需要进行反序列化操作讲数据取出) (4).Java平台允许我们在内存中创建

  • Android实现文件存储并读取的示例代码

    要求: 输入文件名,文件内容分别存储在手机内存和外存中,并且都可以读去取出来. 步骤: 1.创建一个名为CDsaveFile的Android项目 2.编写布局文件activity_main.xml: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layo

  • Android编程中File文件常见存储与读取操作demo示例

    本文实例讲述了Android编程中File文件常见存储与读取操作.分享给大家供大家参考,具体如下: MainActivity文件代码如下: package example.com.myapplication; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; im

  • Android内部存储改变读取权限的方法

    在开发时,手机先要ROOT,然后在通过代码改变权限. <span style="color:#330033;">public synchronized static boolean getRoot(String paramString) { Process process = null; DataOutputStream os = null; try { process = Runtime.getRuntime().exec("su"); os = ne

  • 详解Android四种存储方式

    在Android程序开发中我们经常遇到四种数据存储方式,每种存储方式都各有不同:以下我分别列举了Android开发中的不同存储方式的特点 一,Preferences Preferences是一个较轻量级的存储数据的方法,具体使用方法: 在A中保存值: SharedPreferences.Editor sharedata = getSharedPreferences("data", 0).edit(); sharedata.putString("name","

  • Android使用SharedPreferences存储XML文件的实现方法

    本文实例讲述了Android使用SharedPreferences存储XML文件的实现方法.分享给大家供大家参考,具体如下: SharedPreferences是Android平台上一个轻量级的存储类,主要是保存一些常用的配置比如窗口状态,一般在Activity中 重载窗口状态onSaveInstanceState保存一般使用SharedPreferences完成,它提供了Android平台常规的Long长 整形.Int整形.String字符串型的保存. 在Fragment中的使用方法: @Ov

  • Android用文件存储数据的方法

    本文实例为大家分享了Android用文件存储数据的具体代码,供大家参考,具体内容如下 存储数据示例: private void saveFileData() { BufferedWriter writer = null; try { FileOutputStream out = openFileOutput("data", MODE_PRIVATE);//保存的文件名为"data" writer = new BufferedWriter(new OutputStre

  • python pickle存储、读取大数据量列表、字典数据的方法

    先给大家介绍下python pickle存储.读取大数据量列表.字典的数据 针对于数据量比较大的列表.字典,可以采用将其加工为数据包来调用,减小文件大小 #列表 #存储 list1 = [123,'xiaopingguo',54,[90,78]] list_file = open('list1.pickle','wb') pickle.dump(list1,list_file) list_file.close() #读取 list_file = open('list1.pickle','rb')

  • Python实现序列化及csv文件读取

    这篇文章主要介绍了Python实现序列化及csv文件读取,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.python 序列化: 序列化指的是将对象转化为"串行化"数据形式,存储到硬盘或通过网路传输到其他地方,反序列化是指相反的过程,将读取到串行化数据转化成对象.使用pickle模块中的函数,实现序列化和反序列化操作. 序列化使用: pickle.dump(obj,file) obj是被序列化的对象,file指的是存储的文件. pi

  • Android实现文件存储案例

    本文实例为大家分享了Android实现文件存储的具体代码,供大家参考,具体内容如下 1.文件存储案例 public class TestActivity extends AppCompatActivity { private EditText mFileEdit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.l

随机推荐