在 Android 应用开发中,数据持久化是至关重要的一环,SQLite 作为 Android 内置的轻量级关系型数据库,因其占用资源少、性能优异、无需独立服务器进程而被广泛采用,它允许开发者以结构化的方式存储、查询和管理应用数据,例如用户信息、设置项、缓存数据等,掌握如何在 Android 中创建和管理 SQLite 数据库,是每一位 Android 开发者的必备技能。

核心概念:SQLiteOpenHelper
Android SDK 提供了一个非常重要的辅助类 android.database.sqlite.SQLiteOpenHelper,它极大地简化了数据库的创建和版本管理,开发者无需直接编写复杂的文件创建和版本检查逻辑,只需继承这个类并实现其核心方法即可。SQLiteOpenHelper 主要负责两个关键任务:
- 创建数据库:当应用首次访问数据库,且数据库文件不存在时,它会自动触发创建过程。
- 升级数据库:当应用版本更新,数据库结构需要变更时(如添加新表、修改列),它会提供一个安全的升级通道。
SQLiteOpenHelper 包含两个必须重写的抽象方法和两个常用的实例方法:
onCreate(SQLiteDatabase db):当数据库首次被创建时调用,这里是执行创建表(CREATE TABLE)等初始化语句的最佳位置。onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):当数据库需要升级时调用,开发者可以在这里根据旧版本号oldVersion和新版本号newVersion来执行相应的数据库结构变更逻辑,如ALTER TABLE或DROP TABLE。getReadableDatabase():获取一个可读的数据库对象,如果磁盘空间满,它会以只读方式打开数据库。getWritableDatabase():获取一个可读写的数据库对象,这是最常用的方法,它会尝试以读写方式打开数据库。
创建 SQLite 数据库的详细步骤
下面将通过一个完整的实例,展示如何创建一个名为 user.db 的数据库,并在其中创建一张存储用户信息的 users 表。
第一步:创建数据库辅助类
创建一个继承自 SQLiteOpenHelper 的 Java 或 Kotlin 类,这个类将封装所有与数据库创建和升级相关的逻辑。
// DatabaseHelper.java
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DatabaseHelper extends SQLiteOpenHelper {
// 数据库名称
private static final String DATABASE_NAME = "user.db";
// 数据库版本,每次升级时需要增加此值
private static final int DATABASE_VERSION = 1;
// 表名和列名常量,避免硬编码
public static final String TABLE_USERS = "users";
public static final String COLUMN_ID = "id";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_AGE = "age";
// 创建表的 SQL 语句
private static final String SQL_CREATE_TABLE_USERS =
"CREATE TABLE " + TABLE_USERS + " (" +
COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
COLUMN_NAME + " TEXT NOT NULL, " +
COLUMN_AGE + " INTEGER" +
")";
// 构造函数
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// 当数据库被创建时,执行创建表的 SQL
db.execSQL(SQL_CREATE_TABLE_USERS);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 简单的升级策略:删除旧表,然后重新创建
// 注意:此操作会丢失所有数据,实际项目中应使用更安全的迁移策略
db.execSQL("DROP TABLE IF EXISTS " + TABLE_USERS);
onCreate(db);
}
}
在上述代码中,我们定义了数据库名称、版本号、表名、列名以及创建表的 SQL 语句,构造函数通过 super() 调用父类,传入必要的参数。onCreate 方法执行了 CREATE TABLE 命令。
第二步:在 Activity 中使用数据库
创建好 DatabaseHelper 后,就可以在应用的其他组件(如 Activity、Service)中获取并使用数据库了。

// MainActivity.java
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private DatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. 初始化 DatabaseHelper 实例
dbHelper = new DatabaseHelper(this);
// 2. 获取可写的数据库对象
// 第一次调用此方法时,如果数据库不存在,会触发 DatabaseHelper 的 onCreate 方法
SQLiteDatabase db = dbHelper.getWritableDatabase();
// 3. 数据库已创建并可以使用了
Toast.makeText(this, "数据库创建成功或已存在!", Toast.LENGTH_SHORT).show();
// 此处可以进行增删改查(CRUD)操作...
// 插入一条数据
// ContentValues values = new ContentValues();
// values.put(DatabaseHelper.COLUMN_NAME, "张三");
// values.put(DatabaseHelper.COLUMN_AGE, 25);
// long newRowId = db.insert(DatabaseHelper.TABLE_USERS, null, values);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 4. 在不需要时关闭数据库连接(可选,但推荐)
// dbHelper.close();
}
}
当 MainActivity 启动并调用 dbHelper.getWritableDatabase() 时,系统会检查 /data/data/<your.package.name>/databases/ 目录下是否存在 user.db 文件,如果不存在,就会调用 DatabaseHelper 的 onCreate 方法来创建它。
最佳实践与注意事项
- 异步操作:数据库操作(尤其是查询和大量数据写入)可能是耗时的,直接在 UI 线程执行可能导致应用无响应(ANR),应始终在后台线程(如使用
AsyncTask、ExecutorService或 Kotlin 协程)中执行数据库操作。 - 常量定义:将表名、列名等定义为
public static final常量,可以有效避免因字符串拼写错误导致的运行时异常,并提高代码的可维护性。 - 数据库版本管理:
DATABASE_VERSION是数据库升级的关键,当你需要修改表结构(在users表中添加一个email列)时,应该将DATABASE_VERSION增加(从 1 改为 2),并在onUpgrade方法中编写相应的ALTER TABLE语句,而不是简单地删除旧表,以保留用户数据。
现代替代方案:Room 持久性库
虽然直接使用 SQLiteOpenHelper 和 SQLiteDatabase 功能强大,但代码量较大,容易出错(如 SQL 语句编译时无法检查),Google 推出了 Room 持久性库作为现代 Android 应用的首选方案,Room 在 SQLite 之上提供了一个抽象层,它:
- 简化了数据库操作:通过注解(如
@Entity,@Dao,@Database)大大减少了模板代码。 - 编译时 SQL 验证:在编译时检查 SQL 语句的正确性,避免运行时崩溃。
- 与 LiveData/RxJava/Kotlin Flow 无缝集成:轻松实现响应式数据编程。
对于新项目,强烈推荐使用 Room 库,但理解原生 SQLite 的工作原理,有助于更好地掌握 Room 的底层机制。
相关问答 (FAQs)
问题1:SQLiteOpenHelper 的 onCreate() 和 onUpgrade() 方法分别在什么时候被调用?
解答:onCreate(SQLiteDatabase db) 方法在数据库文件首次被创建时调用,当你通过 getWritableDatabase() 或 getReadableDatabase() 请求一个数据库对象,而系统发现指定名称的数据库文件尚不存在时,就会创建该文件,并立即回调 onCreate 方法,该方法在整个应用的生命周期中只会被调用一次。
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 方法在数据库需要升级时调用,当你修改了 SQLiteOpenHelper 构造函数中传入的版本号(DATABASE_VERSION),使其大于设备上已存在的数据库文件的版本号时,系统就会调用 onUpgrade,你可以根据 oldVersion 和 newVersion 参数来决定执行哪些升级逻辑,例如从版本 1 升级到 2 时添加一个新列,从版本 2 升级到 3 时再添加一个新表。

问题2:我应该直接使用原生 SQLite API 还是使用 Room 库?
解答:
这取决于你的项目需求和个人偏好,但总的原则是:对于新项目,优先推荐使用 Room 库。
-
使用原生 SQLite API (
SQLiteOpenHelper) 的优点是更底层,控制力更强,不需要额外的依赖库,但缺点是代码繁琐,需要手写大量 SQL 语句和模板代码,且 SQL 错误只能在运行时发现,容易导致android.database.sqlite.SQLiteException。 -
使用 Room 库 的优点非常突出:它通过注解极大地简化了代码,将开发者从繁琐的 SQL 编写和对象映射中解放出来,最重要的是,它能在编译时验证 SQL 语句的正确性,提前发现错误,它与 Android 架构组件(如
LiveData,ViewModel,Kotlin Flow)完美集成,让构建响应式、健壮的数据层变得异常简单。
小编总结建议:如果你正在维护一个使用原生 SQLite 的旧项目,或者有非常特殊的数据库操作需求,可以继续使用原生 API,但对于所有新启动的 Android 项目,Room 几乎总是更好的选择,它能显著提高开发效率和代码质量。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!