转载

关于Android开发中Java对象序列化的一次测试

Android开发过程中会遇到很多情况,需要将一个Java序列化,比如序列化一个对象来保存当前一些信息,等下次App启动后再还原。

对象序列化可以有好多种方法,一般最简单的就是实现 Serializable 接口,通过 ObjectOutputStream 写到SD卡中;还有可以将Java对象序列化到数据库中;还可以将Java对象转成一个字符串,把这个字符串写到SD卡中,反序列化时读取这个字符串,并且转成一个Java对象。

如果只保存一个Java对象,你应该不会把它写到数据库中的,一般会使用另外两种方法,但是那种方法好呢?

方法0:实现Serializable接口

写上两段代码

//将Object写入SD卡 private void writeObject(Object result) {  ObjectOutputStream oos = null;  FileOutputStream fileOutputStream = null;  try {   File file = new File(Config.getCachePath() + "bxbxbai");   fileOutputStream = new FileOutputStream(file);   oos = new ObjectOutputStream(fileOutputStream);   oos.writeObject(result);  } catch (Exception e) {   e.printStackTrace();  } finally {   try {    fileOutputStream.close();    oos.close();   } catch (Exception e) {    e.printStackTrace();   }  } } //读取Object private Object readObject() {  Object object = null;  File file = new File(Config.getCachePath() + "bxbxbai");  if (file.isFile()) {   ObjectInputStream ois = null;   FileInputStream fileInputStream = null;   try {    fileInputStream = new FileInputStream(file);    ois = new ObjectInputStream(fileInputStream);    object = ois.readObject();   } catch (Exception e) {    e.printStackTrace();   } finally {    try {     fileInputStream.close();     ois.close();    } catch (Exception e) {     e.printStackTrace();    }   }   return object;  }  return null; }  

方法1:将对象转换成String序列化

//先用Gson将对象转换成String,然后把String写入SD卡 private void writeObjectString(Object result) {  String s = new Gson().toJson(result);  FileOutputStream fileOutputStream = null;  try {   File file = new File(Config.getCachePath() + "bxbxbai_string");   fileOutputStream = new FileOutputStream(file);   BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fileOutputStream));   writer.write(s);   writer.flush();   writer.close();  } catch (Exception e) {   e.printStackTrace();  } finally {   try {    fileOutputStream.close();   } catch (Exception e) {    e.printStackTrace();   }  } } //先读取String,然后转成Java对象 private Object readObjectString() {  File file = new File(Config.getCachePath() + "bxbxbai_string");  if (file.isFile()) {   try {    Scanner scanner = new Scanner(file);    StringBuilder json = new StringBuilder();    while (scanner.hasNext()) {     json.append(scanner.nextLine());    }    scanner.close();    return new Gson.fromJson(json.toString(), SerializeStringResult.class);   } catch (Exception e) {    e.printStackTrace();   }  }  return null; }  

测试

基本的功能代码已经都贴了,下面是测试代码:

private void test() {     try {  //省略创建object代码,result0 和result1 完全一样  StopWatch.begin("writeObject");  writeObject(result0);  StopWatch.end("writeObject");  StopWatch.begin("readObject");  Object o1 = readObject();  StopWatch.end("readObject");  //写String  StopWatch.begin("writeObjectString");  writeObjectString(result1);  StopWatch.end("writeObjectString");  StopWatch.begin("readObjectString");  Object o2 = readObjectString();  StopWatch.end("readObjectString");     } catch (Exception e) {  e.printStackTrace();     } }  

测试数据是地址:地址,测试手机使用LG-D858

测试结果(单位ms)

. writeObject readObject writeObjectString readObjectString
0 324 111 44 66
1 285 104 29 60
2 286 95 30 61
3 271 91 30 60
4 288 94 29 58
5 260 91 28 63
6 273 93 27 60
7 267 92 27 61
8 265 172 27 59
9 299 97 29 64
Average 282 104 30 61

一共测试了10次,平均结果如下:

  • Serializable写:282ms
  • Serializable读:104ms
  • 转String写:30ms
  • 转String读:61ms

也就是说将Java对象转成String再进行序列化以及反序列化可以大大减少时间。

Once upon a time, this used the standard Java Object{Input,Output}Stream, but the default implementation relies heavily on reflection (even for standard types) and generates a ton of garbage.

上面这段话是我几个月前我看Volley源码的时候看到的,在 DiskBasedCache 类中,大致的意思就是之前Volley也是用Java对象的序列化来缓存HTTP 头信息的,后来发现 Object{Input,Output}Stream 序列化严重依赖反射机制, 会在序列化过程中产生大量的零时对象,从而更加频繁的触发GC ,后来Google的工程师自己写了一个简单的序列化和反序列化方法

总结

从测试结果中可以看到,将Java对象转换成String,然后在把String序列化可以节省大量的时间。不仅如此, Object{Input,Output}Stream 序列化方法严重依赖Java反射机制,在序列化过程中会产生大量的零时对象,会更加频繁的触发GC操作

所以,我觉得还是把Java对象转成String再序列化吧,可以提升不少性能呢 :)

正文到此结束
Loading...