概述
初学 Android 时,我们所了解的数据存储方式是把数据存储到变量里(store it in variables)。但是变量的生命周期和 Activity 的一样长,可以将它想象成临时存储器(temporary storage)。我们需要一个更永久(more permanent)的方式来存储用户数据。当你关闭应用并重新打开时,用户数据依然存在。这个概念就叫做数据持久化(data persistence),其中的某些方式是将数据存储到文件或数据库中。接下来主要介绍的是数据库这一方式。
在此之前,我们可以参考 计算机内存和硬盘存储空间之间的区别,了解计算机的两种存储方式临时存储和永久存储。
三种 Android 存储方式
我们将讨论三种 Android 存储方式,使我们能够将数据直接保存到设备上。
存储方式 | 描述 |
---|---|
Files | 保存大型媒体文件,例如图片、图书、歌曲或视频文件 |
SharedPreferences | 保存用户偏好设置,例如即时通讯中的消息提醒方式(震动、声音、声音+震动),更适合存储单个重要信息 |
SQLite Databases | 数据库类型(有组织的数据集合),保存大量相关的结构化文本类数据(structured data),就像电子表格中的行和列结构 |
一定要注意,很多 Android 应用会结合使用上面表格中的三种存储方式。例如相机应用,它会使用文件来将照片保存到本地,同时使用 SQLite 数据库来存储元数据(信息的信息,例如关于照片的时间,地点,说明信息等)。关于更详细的 Android 数据存储可查看Android 中的存储选项
SQLite
SQLite 是一种数据库,使我们的应用和与之交互的设备上创建一个本地数据库。Lite 一词是指典型数据库的轻量级版本(lightweight version)。对应地就存在着重量级数据库,例如 MySQL,它可以提供更加复杂的功能。SQLite 不需要服务器,数据存储在设备的本地文本文件里。SQLite 是免费开源的,并且是 Android 自带的数据库这就是为什么需要学习这一特定类型的数据库。
我们不需要下载或安装任何内容,就能在 Android 应用中使用 SQLite。虽然手机上已经具有 SQLite,但是计算机并没有预装 SQLite。接下来介绍如何在计算机上下载并安装 SQLite。
安装
Windows
- 下载正确的 zip 文件。
- 创建一个文件夹,叫做 C:>sqlite,并将 zip 文件解压到这里面。
- 将 C:>sqlite 添加到你的 PATH 环境变量里。
- 在命令提示窗口里输入 sqlite3 命令。
要下载正确的 zip 文件,你需要转到此处并下载下面两个文件:
- sqlite-shell-win32-*.zip
- sqlite-dll-win32-*.zip
Mac OS X
最新版本的 OS X 已经预装了 SQLite,所以可以不需要执行任何操作。打开终端,输入 sqlite3,然后按下 Enter 键。如果终端显示如下类似内容则说明预装了。
如果没有显示,就需要自己安装。下载相关文件,在终端程序输入一些命令。
首先转到此处下载sqlite-autoconf-*.tar.gz。然后在终端输入如下命令:
$tar xvfz sqlite-autoconf-3071502.tar.gz
$cd sqlite-autoconf-3071502
$./configure --prefix=/usr/local
$make
$make install
SQLite 就安装上 Mac 了。
SQL 语言
SQLite 程序可以理解为另一种计算机语言叫做 SQL,它是 structured query language(结构化查询语言)的缩写。 它是一种经过优化专门用于数据库的计算机语言。Java 语言可以创建类、变量和控制流程语句等,而 SQL 专门用来创建表格,然后添加和移除及操纵条目。
设计和创建数据库
SQLite 中的类型
SQLite 使用更加宽泛的类型系统。
类型 | 描述 |
---|---|
NULL | 值为 null |
INTEGER | 整型赋值 |
REAL | 值为浮点型 |
TEXT | 值为字符串 |
BLOB | 数据完全按照输入的样式存储起来,例如图片、二进制数 |
场景示例
1.宠物收容所的宠物信息
Attribute | Storage Class |
---|---|
Name(宠物名) | TEXT(文本) |
Breed(品种) | TEXT(文本) |
Gender(公母) | INTEGER(0-未知,1-公、2-母) |
Weight(体重) | INTEGER(为了简单) |
2.网上商店中耳机库存情况统计
Attribute | Storage Class |
---|---|
Name(名称) | TEXT(文本) |
Price(价格) | INTEGER(整型更简单) |
Style(佩戴形式) | INTEGER(1-耳塞式、2-头戴式、3-挂耳式、4-入耳式) |
In Stock?(库存情况) | INTEGER(0-缺货、1-有货) |
Description(说明) | TEXT(文本) |
存储一位数比存储整个单词占用更少的空间,其次长的字符串可能不太精确。
创建表格
CREATE TABLE <table_name> (<column_name_1> <data_type_1>, <column_name_2> <data_type_2>, ...);
以上面的场景2耳机为例
CREATE TABLE headphones (_id INTEGER, name TEXT, price INTEGER, style INTEGER, in_stock INTEGER, description TEXT);
注意,SQLite 关键字都是大写。在每个表格里都应该具有 ID 来唯一标识对象,因为对象的其它属性可能会有重复,导致混乱。
查询表格
sqlite> .tables
headphones
sqlite> .schema headphones
CREATE TABLE headphones (_id INTEGER, name TEXT, price INTEGER, style INTEGER, in_stock INTEGER, description TEXT);
sqlite> PRAGMA TABLE_INFO(headphones);
0|_id|INTEGER|0||0
1|name|TEXT|0||0
2|price|INTEGER|0||0
3|style|INTEGER|0||0
4|in_stock|INTEGER|0||0
5|description|TEXT|0||0
使用 .tables
来检查表格是否已创建,系统返回了表格名称 headphones
,但是返回的信息并不多。我们还可以使用另一个指令: .schema <table_name>
显示用来创建该表格的语句。使用指令 PRAGMA TABLE_INFO(<table_name>);
来显示包括所有列的名称和类型。
删除表格
DROP TABLE <table_name>;
,慎重使用。
增删改查
以场景1宠物为例:
sqlite> .tables
sqlite> CREATE TABLE pets (_id INTEGER, name TEXT, breed TEXT, gender INTEGER, weight INTEGER);
创建好表格后,我们就可以开始向表格中添加行,并读取和操作其中的数据。
通过表格结构,我们很容易看出操作流程。
SELECT <columns> FROM <table_name>
// * 通配符,所有行和列
SELECT * FROM pets;
INSERT INFO <table_name> (<columns_name_1>, <columns_name_2>, ...) VALUES (<value_1>, <value_2>, ...);
INSERT INTO pets (_id, name, breed, gender, weight) VALUES (1, "Tommy", "pomeranian", 1, 4);
sqlite> .header on
sqlite> .mode column
sqlite> SELECT * FROM pets;
_id name breed gender weight
---------- ---------- ---------- ---------- ----------
1 Tommy pomeranian 1 4
2 Garfield Tabby 2 8
1 Binx Bombay 1 14
从输出内容可以看出,本来应该唯一的 ID,不再唯一。该怎么办?
SQL 提供了便捷的关键字:PRIMARY KEY
、AUTOINCREMENT
、NOT NULL
、DEFAULT <value>
。
sqlite> CREATE TABLE headphones (_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, price INTEGER, style INTEGER, in_stock INTEGER, description TEXT);
PRIMARY KEY:将相关列标为唯一标识的行,该属性通常与表示每个表格只能有一个主键。它可以确保唯一性。同时添加 AUTO INCREMENT 表示没有插入 ID 也会自动使其加1,无需指定数字。
sqlite> INSERT INTO headphones (name, price, style, in_stock, description) VALUES ("DJ Bliss Red Headphones", 7198, 2, 1, "These awesome headphones will make you feel like a DJ");
sqlite> INSERT INTO headphones (name, price, style, in_stock, description) VALUES ("CityRunner Active Wireless Headphones", 17198,3, 0, "On the go city dwellers will love these wireless headphones");
sqlite> SELECT * FROM headphones;
_id name price style in_stock description
---------- ----------------------- ---------- ---------- ---------- -----------------------------------------------------
1 DJ Bliss Red Headphones 7198 2 1 These awesome headphones will make you feel like a DJ
2 CityRunner Active Wirel 17198 3 0 On the go city dwellers will love these wireless head
在上面的条件下,如果再插入一条 ID 为 1 的数据,系统就会提示错误
sqlite> INSERT INTO headphones (_id, name, price, style, in_stock, description) VALUES (1, "CityRunner Active Wireless Headphones", 17198,3, 0, "On the go city dwellers will love these wireless headphones");
Error: UNIQUE constraint failed: headphones._id
NOT NULL:表示向表格中插入某个值时,必须具有相关的值,不能为空。
DEFAULT:表示在没有给定值时会添加一个默认值。
// 选择
SELECT FROM <table_name> WHERE 条件;
// 排序
SELECT * FROM <table_name> ORDER BY 列属性 ASC/DESC(升序/降序)
// 条件使我们的指令更加具体,指定需要的
UPDATE <table_name> SET 更新内容 条件;
DELETE FROM <table_name>;
文章只是作为个人记录学习使用,如有不妥之处请指正,谢谢。