安卓开发中的数据库使用指南
安卓常用数据库类型
安卓开发中常见的数据库方案包括:
SQLite基础操作
-
创建数据库
// 获取可写数据库 SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase("app.db", null); // 创建表 db.execSQL("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)");
-
增删改查示例
| 操作 | SQL语句 | Android代码片段 |
|————|—————————————–|——————————————|
| 插入 |INSERT INTO users (name) VALUES ('Alice')
|db.execSQL("INSERT INTO users (name) VALUES (?)", new Object[]{"Alice"});
|
| 查询 |SELECT FROM users
|Cursor cursor = db.rawQuery("SELECT FROM users", null);
|
| 更新 |UPDATE users SET name='Bob' WHERE id=1
|db.execSQL("UPDATE users SET name=? WHERE id=?", new Object[]{"Bob", 1});
|
| 删除 |DELETE FROM users WHERE id=1
|db.execSQL("DELETE FROM users WHERE id=?", new Object[]{1});
|
Room组件进阶
-
定义实体类
@Entity(tableName = "users")
public class User {
@PrimaryKey(autoGenerate = true)
public int id;
@ColumnInfo(name = "name")
public String name;
} -
创建DAO接口
@Dao public interface UserDao { @Insert void insert(User user); @Query("SELECT FROM users WHERE id=:userId") User getUserById(int userId); @Update void update(User user); @Delete void delete(User user); }
-
构建数据库
@Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); }
关键问题与解决方案
-
主线程操作数据库导致卡顿
// Room + LiveData示例
LiveData<List<User>> users = appDatabase.userDao().getAllUsers();
users.observe(lifecycleOwner, list -> {
// 更新UI
}); -
数据库版本升级数据迁移
- 实现:重写
RoomDatabase.Migration
或SQLiteOpenHelper.onUpgrade
。static final Migration MIGRATION_1_2 = new Migration(1, 2) { @Override public void migrate(SupportSQLiteDatabase database) { database.execSQL("ALTER TABLE users ADD COLUMN age INTEGER"); } };
- 实现:重写
最佳实践
- 使用加密数据库:通过
SQLiteOpenHelper
的encrypt()
方法保护敏感数据。 - 避免内存泄漏:确保
SQLiteOpenHelper
单例模式,避免多次创建实例。 - 选择合适框架:简单需求用SQLite,复杂业务优先Room,高频读写考虑Realm。
相关问题与解答
问题1:Room的@Query参数如何处理null值?
- 解答:Room的
@Query
不支持直接传递null
参数,需使用:parameter
占位符并传入null
。@Query("SELECT FROM users WHERE age > :minAge") List<User> getUsers(int minAge); // minAge=null会触发异常
正确做法:在DAO中处理
null
逻辑,或使用@Nullable
注解配合条件判断。
问题2:SQLite多线程并发写入会导致什么问题?
- 解答:SQLite默认支持多线程读取,但写入需加锁,未正确处理可能引发:
- 数据竞争(脏读、不可重复读)
- 数据库锁定导致ANR(Application Not Responding)
解决方案:使用ContentProvider
集中管理访问,或通过synchronized
块控制