Android设备上的应用都有一个沙盒目录。将文件保存在沙盒中,可阻止其他应用甚至是设备用户的访问。
应用沙盒目录是/data/data/[your package name]的子目录。例如,Criminalintent应用的沙盒目录是/data/data/com.bignerdranch.android.criminalintent。
需要保存大量数据时,大多数应用都不会使用类似txt这样的普通文件。原因很简单:假设将crime记录写入了这样的文件,在仅需要修改crime标题时,就得首先读取整个文件的内容,完成修改后再全部保存。数据量大的话,这将非常耗时。
那么这该怎么办呢?这时候就需要用到SQLite了。SQLite是类似于MySQL和Postgresql的开源关系型数据库。不同于其他数据库的是,SQLite使用单个文件存储数据,使用SQLite库读取数据。Android标准库包含SQLite库以及配套的一些Java辅助类。
创建数据库前,首先要清楚存储什么样的数据。CriminalIntent应用要保存的是一条条crime记录,这需要定义如下图所示的crimes数据表。
crimes数据表
定义Schema的方式众多,如何选择往往因人而异。处理类似的任务,开发人员都有个共同的目标:“不要重复造轮子。”实际上,这也是人人都应遵守的编程准则:多花时间思考复用代码的编写和调用,避免在应用中到处使用重复代码。
基于上述准则,我们可以使用能统一定义模型层对象(如Crime)的ORM(对象关系映射)工具。不过,对于CriminalIntent应用,南昌APP开发公司建议直接在Java代码中定义描述表名和数据字段的数据库schema。
首先,我们来创建定义schema的Java类。创建时,命名类为CrimeDbSchema,同时在新建类对话框中输入包名database.CrimeDbSchema。这样,就可以将CrimeDbSchema.java文件放入专门的database包中,实现数据库操作相关代码的组织和归类。
在CrimeDbSchema类中,再定义一个描述数据表的CrimeTable内部类,如下代码所示。
定义CrimeTable内部类(CrimeDbSchema.java)
public class CrimeDbSchema {
public static final class CrimeTable {
public static final String NAME = "crimes";
}
}
CrimeTable内部类唯一的用途就是定义描述数据表元素的String常量。首先要定义的是数据库表名(CrimeTable.NAME)。
接下来定义数据表字段
定义数据表字段(CrimeDbSchema.java)
public class CrimeDbSchema {
public static final class CrimeTable {
public static final String NAME = "crimes";
public static final class Cols {
public static final String UUID = "uuid";
public static final String TITLE = "title";
public static final String DATE = "date";
public static final String SOLVED = "solved";
}
}
}
有了这些数据表元素,就可以在Java代码中安全地引用了。例如,CrimeTable.Cols.TITLE就是指crime记录的title字段。此外,这种定义方式还给修改字段名称或新增表元素带来了方便。