什么是NoSql
?从表面上可以理解成,存储在数据库中的并不是一条条的数据,而是一个个Map对象。
NoSql
在Android上应用得不多,Paper
是目前刚出现的性能比较好而且比较小巧的一款。翻翻源代码,分析一下他的原理
介绍
代码地址: github.com/pilgr/Paper
compile 'io.paperdb:paperdb:1.1'
使用
Paper.init(context);
Paper.book().write("city", "Lund");
Paper.book().write("task-queue", queue);
Paper.book().write("countries", countryCodeMap);
String city = Paper.book().read("city");
LinkedList queue = Paper.book().read("task-queue");
HashMap countryCodeMap = Paper.book().read("countries");
分析
paper代码不多,大致结构是
- io.paperdb
- serializer
- NoArgCollectionSerializer.java
- Book.java
- DbStoragePlainFile.java
- Paper.java
- PaperDbException.java
- PaperTable.java
- Storage.java
- serializer
果然很小巧,接下来逐步分析:
Paper.java
核心代码是
private static final ConcurrentHashMap
mBookMap = new ConcurrentHashMap<>();
这个类储存了一个Book
集合。提供了一些方法查询、创建、删除数据。
Book.java
核心代码
protected Book(Context context, String dbName) {
mStorage = new DbStoragePlainFile(context.getApplicationContext(), dbName)
}
book层只是Storage的代理,基本上都是诸如此类的方法:
public void delete(String key) {
mStorage.deleteIfExists(key);
}
Storage.java
一个接口,声明了增删改查方法
interface Storage {
void destroy();
void insert(String key, E value);
E select(String key);
boolean exist(String key);
void deleteIfExists(String key);
List
getAllKeys();
}
在Book
中,Storage
的具体的实现是DbStoragePlainFile
DbStoragePlainFile.java
首先代码内定义了Kryo对象
private Kryo getKryo() {
return mKryo.get();
}
private final ThreadLocal
mKryo = new ThreadLocal
() {
protected Kryo initialValue() {
return createKryoInstance();
}
};
Kryo : github.com/EsotericSof…
猜测使用Kryo做序列化。看看保存方法的实现能不能证明猜测
@Override
public synchronized
void insert(String key, E value) {
assertInit();
final PaperTable
paperTable = new PaperTable<>(value);
final File originalFile = getOriginalFile(key);
final File backupFile = makeBackupFile(originalFile);
....
}
每个key
都对应了一个File
对象?难道Paper
的原理只是建立了一个目录,然后把每个key的对象序列化之后存到目录下的文件里?
private
void writeTableFile(String key, PaperTable
paperTable, File originalFile, File backupFile) {
try {
FileOutputStream fileStream = new FileOutputStream(originalFile);
final Output kryoOutput = new Output(fileStream);
getKryo().writeObject(kryoOutput, paperTable);
kryoOutput.flush();
fileStream.flush();
sync(fileStream);
kryoOutput.close();
backupFile.delete();
} catch (IOException | KryoException e) {
if (originalFile.exists()) {
if (!originalFile.delete()) {
throw new PaperDbException("Couldn't clean up partially-written file "
+ originalFile, e);
}
}
throw new PaperDbException("Couldn't save table: " + key + ". " +
"Backed up table will be used on next read attempt", e);
}
}
果然如此
总结
Paper
作为新出的比较火的NoSql
存储库,实现思路还是很棒的。
首先是代码量很小,实现简单,继承容易。
其次提供了一套函数式Api,调用方便。
最重要的是在数据存储原理上,他不像SqLite或者其他的NoSql存储,将数据打包成数据库。而是建立了一个数据文件夹,将每个Key使用Kryo序列化之后存储在文件夹内。
这种实现方式的优点是,查询数据时不需要读取索引文件。数据 数量 小时速度快
缺点也很多,例如文件夹内文件过多可能造成性能下降(单条数据太大倒不会造成性能影响)、只能存储一级Map,加载会将所有内容都加载进内存。等等
但是在Android平台上,确实是一个很棒的NoSql
库