SQLite
核心特性
- 轻量级:无需额外依赖,Android系统原生支持
- ACID特性:支持原子性/一致性/隔离性/持久化事务
- SQL语法:支持标准SQL语句(CRUD操作)
- 单文件存储:默认存储路径
/data/data/包名/databases/
基础操作示例
// 创建数据库助手类
public class DBHelper extends SQLiteOpenHelper {
public DBHelper(Context context) {
super(context, "app.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE user(id INTEGER PRIMARY KEY,name TEXT)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS user");
onCreate(db);
}
}
// 增删改查操作
SQLiteDatabase db = helper.getWritableDatabase();
// 插入
db.execSQL("INSERT INTO user(name) VALUES(?)", new Object[]{"John"});
// 查询
Cursor cursor = db.rawQuery("SELECT FROM user", null);
while(cursor.moveToNext()){
int id = cursor.getInt(0);
String name = cursor.getString(1);
}
对象关系映射库:Room
核心优势
特性 |
说明 |
编译时验证 |
通过注解处理器提前发现SQL错误 |
流畅API |
支持LiveData、RxJava等响应式编程 |
类型安全 |
避免手写SQL的字段类型错误 |
迁移支持 |
提供Schema迁移工具 |
实体定义示例
@Entity(tableName = "user")
public class User {
@PrimaryKey(autoGenerate = true)
public int id;
@ColumnInfo(name = "username")
public String name;
// 必须包含空构造函数
public User(){}
}
DAO接口示例
@Dao
public interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(User... users);
@Query("SELECT FROM user WHERE id=:userId")
LiveData<User> getUserById(int userId);
@Update
void update(User user);
@Delete
void delete(User user);
}
NoSQL解决方案:Realm
核心特性对比表
维度 |
SQLite/Room |
Realm |
数据模型 |
表结构 |
对象嵌套结构 |
线程模型 |
多线程需手动管理 |
跨线程自动同步 |
查询能力 |
SQL语法 |
类似LINQ的流畅接口 |
性能 |
中等 |
极优(接近内存速度) |
存储格式 |
文本文件 |
二进制文件 |
实时更新示例
Realm realm = Realm.getDefaultInstance();
realm.executeTransaction(r -> {
User user = r.createObject(User.class, 1); // 自动生成主键
user.name = "Alice";
});
// 监听数据变化
realm.where(User.class)
.findAllAsync()
.addChangeListener((users, changeSet) -> {
// 数据变更回调
});
云数据库服务:Firebase Firestore
核心功能矩阵
功能 |
Firebase Firestore |
本地数据库方案 |
实时同步 |
△毫秒级离线数据同步 |
×需自建同步机制 |
多平台支持 |
△Web/iOS/Android通用 |
×平台限定 |
安全规则 |
△服务器端数据校验 |
×客户端校验风险 |
计费模式 |
△按读写操作量收费 |
○完全免费 |
查询性能 |
○支持复杂查询 |
△SQLite限制较多 |
安全规则示例
// firestore.rules
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
数据加密与安全
SQLCipher集成步骤
- 添加依赖:
implementation 'net.zetetic:android-database-sqlcipher:4.5.0'
- 修改DBHelper:
super(context, "encrypted.db", factory, 1);
- 设置工厂:
SQLiteDatabase.getBytes(key.getBytes());
- 每次操作前调用:
db.execSQL("PRAGMA key='your-key'");
Android Keystore使用对比
存储类型 |
Keystore |
SharedPreferences |
数据安全性 |
△生物识别加密 |
×明文存储 |
访问控制 |
△权限粒度控制 |
×全局可读 |
备份策略 |
○自动云备份支持 |
△可能泄露到备份文件 |
适用场景 |
△敏感信息存储 |
×普通配置参数 |
问题与解答
Q1:何时应该选择Room而不是直接使用SQLite?
A:当项目需要:
- 编译时SQL校验避免运行时错误
- 响应式编程支持(LiveData/RX)
- 类型安全的DAO接口
- 自动化迁移工具时,应优先使用Room,直接使用SQLite更适合简单临时存储或对性能有极致要求的原始操作场景。
Q2:Realm的线程安全机制是如何实现的?
A:Realm采用自动脏数据检测+零拷贝视图机制:
- 每个线程维护独立的Realm实例
- 跨线程访问时自动触发数据同步
- 通过代理对象实现只读视图,避免多线程冲突
- 写操作自动触发其他线程的数据失效重