一、初识SQLite:从零开始认识这个"轻量级"数据库
说实话,我刚接触Android开发那会儿,对数据库是有点发怵的。总觉得数据库是后端工程师才需要操心的事,我们前端写写界面、存个SharedPreferences不就够了?后来被打脸了——项目越做越大,数据越来越复杂,SharedPreferences根本撑不住。嗯,今天我们就来聊聊SQLite,这个Android开发绕不开的"老朋友"。
1.1 SQLite到底是什么?
SQLite,说白了就是一个嵌入式关系型数据库引擎。它不像MySQL、PostgreSQL那样需要独立安装服务端,而是直接以库的形式嵌入到应用程序中。你想想看,一个数据库只有几百KB大小,却能支持标准的SQL语法,这本身就是件很酷的事。
我在项目中遇到过最极端的例子——一个离线地图App,本地存储了上百万条POI数据,用SQLite查询依然能保持在毫秒级别。这就是它的魅力所在。
SQLite核心特点:
- 零配置:不需要安装、不需要管理员、不需要启动服务
- 自包含:整个数据库就是一个单一的文件
- 轻量级:库体积仅约500KB
- 可靠性:支持ACID事务,崩溃恢复机制完善
- 跨平台:Windows、Linux、macOS、Android、iOS都能跑
1.2 SQLite在Android中的地位
在Android系统里,SQLite可不是什么"可选组件"。它是系统级内置的数据库引擎。什么意思呢?就是每个Android设备出厂时就自带SQLite,不需要开发者额外引入任何依赖。
我个人习惯把Android的数据存储方式分成三类:
| 存储方式 | 适用场景 | 数据复杂度 |
|---|---|---|
| SharedPreferences | 简单键值对、用户偏好设置 | 低 |
| SQLite数据库 | 结构化数据、大量数据、复杂查询 | 高 |
| 文件存储 | 图片、视频、大文件 | 中 |
你看,SQLite正好卡在中间偏上的位置。它不像SharedPreferences那么"简陋",也不像文件存储那么"原始"。对于大多数App来说,SQLite就是那个"刚刚好"的选择。
1.3 SQLite vs SharedPreferences:什么时候该用谁?
这个问题我经常被问到。很多新手开发者习惯把所有数据都往SharedPreferences里塞,结果项目一复杂就后悔莫及。
我曾经接手过一个项目,里面用SharedPreferences存了上千条用户操作记录。每次读取都要遍历整个文件,性能差到令人发指。更可怕的是,SharedPreferences是一次性加载到内存的,数据量一大,直接OOM。
来,我们做个对比:
| 对比维度 | SharedPreferences | SQLite |
|---|---|---|
| 数据结构 | 键值对(Map) | 关系型表结构 |
| 查询能力 | 只能按key查 | 支持SQL:WHERE、JOIN、GROUP BY等 |
| 数据量上限 | 建议不超过100条 | 百万级无压力 |
| 线程安全 | 不推荐多线程操作 | 内置锁机制,支持并发 |
| 事务支持 | 不支持 | 完整ACID事务 |
| 数据类型 | 基本类型 + String + Set | NULL/INTEGER/REAL/TEXT/BLOB |
我的建议:
- 存用户登录状态、主题颜色、语言偏好 → SharedPreferences
- 存聊天记录、商品列表、订单数据 → SQLite
- 如果数据需要排序、过滤、聚合 → 直接上SQLite
1.4 创建你的第一个数据库
好了,理论说完了,我们来动手。在Android里操作SQLite,最正统的方式是使用SQLiteOpenHelper这个抽象类。
为什么不用直接new一个SQLiteDatabase?因为数据库的创建和版本管理是个麻烦事。你想想看,用户升级App时,数据库结构变了怎么办?SQLiteOpenHelper就是专门解决这个问题的。
来看代码:
public class MyDatabaseHelper extends SQLiteOpenHelper {
// 数据库名称
private static final String DATABASE_NAME = "my_first_db.db";
// 数据库版本号
private static final int DATABASE_VERSION = 1;
// 建表SQL语句
private static final String CREATE_TABLE_USER =
"CREATE TABLE user (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
"name TEXT NOT NULL," +
"age INTEGER," +
"phone TEXT UNIQUE" +
")";
public MyDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// 第一次创建数据库时调用
db.execSQL(CREATE_TABLE_USER);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 数据库版本升级时调用
db.execSQL("DROP TABLE IF EXISTS user");
onCreate(db);
}
}
这段代码干了三件事:
- 定义了一个叫
my_first_db.db的数据库文件 - 创建了一张
user表,包含id、name、age、phone四个字段 - 处理了数据库的创建和升级逻辑
注意:上面的onUpgrade方法直接删表重建,这在生产环境是绝对不允许的!真实项目中应该用ALTER TABLE或者做数据迁移。这里只是为了演示,千万别学我这么干。
接下来,在Activity或Fragment里使用它:
// 获取可写数据库实例
MyDatabaseHelper helper = new MyDatabaseHelper(this);
SQLiteDatabase db = helper.getWritableDatabase();
// 插入一条数据
ContentValues values = new ContentValues();
values.put("name", "张三");
values.put("age", 25);
values.put("phone", "13800138000");
long result = db.insert("user", null, values);
if (result != -1) {
Log.d("SQLite", "插入成功,行ID:" + result);
} else {
Log.e("SQLite", "插入失败");
}
// 别忘了关闭数据库
db.close();
运行这段代码后,你可以在设备的/data/data/你的包名/databases/目录下找到my_first_db.db文件。用SQLite浏览器打开它,就能看到我们刚刚插入的数据。
为什么会这样?因为getWritableDatabase()方法内部会检查数据库文件是否存在。如果不存在,就调用onCreate()创建;如果存在但版本号变了,就调用onUpgrade()升级。这个机制保证了数据库的"一次创建,终身维护"。
知识体系总览
下面这张图帮你理清本章的核心脉络:
这张图把本章内容串起来了。从SQLite是什么,到它在Android里的定位,再到和SharedPreferences的对比,最后落到实战——创建第一个数据库。每一步都是环环相扣的。
好了,第一章就到这里。记住,数据库是App的"记忆",而SQLite就是Android赋予我们最趁手的工具。下一章我们会深入SQLite的增删改查,到时候再聊。
公众号:蓝海资料掘金营,微信deep3321