Android开发过程中会遇到很多情况,需要将一个Java序列化,比如序列化一个对象来保存当前一些信息,等下次App启动后再还原。
对象序列化可以有好多种方法,一般最简单的就是实现 Serializable
接口,通过 ObjectOutputStream
写到SD卡中;还有可以将Java对象序列化到数据库中;还可以将Java对象转成一个字符串,把这个字符串写到SD卡中,反序列化时读取这个字符串,并且转成一个Java对象。
如果只保存一个Java对象,你应该不会把它写到数据库中的,一般会使用另外两种方法,但是那种方法好呢?
写上两段代码
//将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; }
//先用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
. | 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次,平均结果如下:
也就是说将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再序列化吧,可以提升不少性能呢 :)