在 Android 应用开发中,本地数据管理是构建离线功能、提升用户体验的核心环节。SQLite 作为轻量级嵌入式数据库,凭借其零配置、事务支持和高效查询能力,成为存储结构化数据的首选方案。结合报表生成技术,开发者可实现数据可视化、统计分析及导出功能,满足业务监控、用户行为分析等场景需求。本文将系统讲解 SQLite 数据库的 CRUD 操作、性能优化策略,以及如何基于本地数据生成动态报表,助力开发者打造稳定、高效的数据驱动型应用。
轻量级:数据库文件仅需一个 .db 文件,无需单独服务器进程。
ACID 兼容:支持事务(Transaction),确保数据一致性。
跨平台:数据文件可直接在 iOS、Web 等平台复用。
典型场景:用户配置存储、离线缓存、本地日志记录、小型 CRM 系统。
通过 SQLiteOpenHelper 管理生命周期:
javapublic class DatabaseHelper extends SQLiteOpenHelper { private static final String DB_NAME = "app_data.db"; private static final int DB_VERSION = 1; public DatabaseHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); } @Override public void onCreate(SQLiteDatabase db) { // 创建用户表 db.execSQL("CREATE TABLE users (" + "id INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT NOT NULL," + "email TEXT UNIQUE," + "created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 版本升级时迁移数据 db.execSQL("DROP TABLE IF EXISTS users"); onCreate(db); }}javapublic long addUser(String name, String email) { SQLiteDatabase db = getWritableDatabase(); ContentValues values = new ContentValues(); values.put("name", name); values.put("email", email); return db.insert("users", null, values); // 返回行 ID,失败返回 -1}javapublic List<User> getAllUsers() { List<User> users = new ArrayList<>(); SQLiteDatabase db = getReadableDatabase(); Cursor cursor = db.query("users", new String[]{"id", "name", "email"}, // 查询列 null, null, null, null, "created_at DESC"); // 按时间降序 while (cursor.moveToNext()) { long id = cursor.getLong(cursor.getColumnIndex("id")); String name = cursor.getString(cursor.getColumnIndex("name")); users.add(new User(id, name, email)); } cursor.close(); return users;}java// 更新用户邮箱public int updateUserEmail(long id, String newEmail) { SQLiteDatabase db = getWritableDatabase(); ContentValues values = new ContentValues(); values.put("email", newEmail); return db.update("users", values, "id=?", new String[]{String.valueOf(id)});}// 删除用户public int deleteUser(long id) { SQLiteDatabase db = getWritableDatabase(); return db.delete("users", "id=?", new String[]{String.valueOf(id)});}为高频查询字段添加索引:
java@Overridepublic void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE users (...)"); db.execSQL("CREATE INDEX idx_user_email ON users(email)"); // 加速邮箱查询}避免过度索引:索引会占用存储空间并降低写入性能,仅在 WHERE、JOIN 条件字段上添加。
使用事务包裹批量插入:
javapublic void batchInsertUsers(List<User> userList) { SQLiteDatabase db = getWritableDatabase(); db.beginTransaction(); try { for (User user : userList) { ContentValues values = new ContentValues(); values.put("name", user.getName()); db.insert("users", null, values); } db.setTransactionSuccessful(); // 标记事务成功 } finally { db.endTransaction(); // 提交或回滚 }}避免 SELECT *:仅查询需要的列,减少 I/O 开销。
使用 LIMIT 分页:大数据集查询时限制返回行数。
启用 WAL 模式(Android 7.0+):
java// 在 DatabaseHelper 的构造函数中启用public DatabaseHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); // 开启 WAL 模式提升并发性能 SQLiteDatabase.releaseMemory(); // 可选:释放缓存}常见类型:销售趋势图、用户活跃度热力图、库存盘点表。
数据来源:SQLite 查询结果 + 时间聚合(如按日/月统计)。
输出格式:RecyclerView 列表、MPAndroidChart 图表、CSV/Excel 导出。
java// 查询每日新增用户数(按创建日期分组)public List<DailyUserCount> getDailyUserCounts() { List<DailyUserCount> result = new ArrayList<>(); SQLiteDatabase db = getReadableDatabase(); String sql = "SELECT strftime('%Y-%m-%d', created_at) AS date, " + "COUNT(*) AS count FROM users GROUP BY date ORDER BY date"; Cursor cursor = db.rawQuery(sql, null); while (cursor.moveToNext()) { String date = cursor.getString(cursor.getColumnIndex("date")); int count = cursor.getInt(cursor.getColumnIndex("count")); result.add(new DailyUserCount(date, count)); } cursor.close(); return result;}java// 在 Activity/Fragment 中绑定数据List<DailyUserCount> dataList = dbHelper.getDailyUserCounts();List<Entry> entries = new ArrayList<>();for (int i = 0; i < dataList.size(); i++) { entries.add(new Entry(i, dataList.get(i).getCount()));}LineDataSet dataSet = new LineDataSet(entries, "每日新增用户");LineChart chart = findViewById(R.id.chart);chart.setData(new LineData(dataSet));chart.invalidate(); // 刷新图表javapublic void exportUsersToCsv(Context context) { List<User> users = dbHelper.getAllUsers(); StringBuilder csvContent = new StringBuilder("id,name,email,created_at\n"); for (User user : users) { csvContent.append(user.getId()).append(",") .append(user.getName()).append(",") .append(user.getEmail()).append(",") .append(user.getCreatedAt()).append("\n"); } // 保存到应用目录 File file = new File(context.getExternalFilesDir(null), "users_export.csv"); try (FileOutputStream fos = new FileOutputStream(file)) { fos.write(csvContent.toString().getBytes()); Toast.makeText(context, "导出成功: " + file.getAbsolutePath(), Toast.LENGTH_LONG).show(); } catch (IOException e) { e.printStackTrace(); }}java// 查询用户及其订单信息(假设存在 orders 表)public List<UserWithOrders> getUsersWithOrders() { List<UserWithOrders> result = new ArrayList<>(); SQLiteDatabase db = getReadableDatabase(); String sql = "SELECT u.id, u.name, o.order_id, o.amount " + "FROM users u LEFT JOIN orders o ON u.id = o.user_id"; Cursor cursor = db.rawQuery(sql, null); // 按用户 ID 分组处理(需在代码中实现逻辑) // ... return result;}优势:编译时 SQL 校验、LiveData 支持、简化样板代码。
示例代码:
kotlin@Entitydata class User( @PrimaryKey val id: Long, val name: String, val email: String)@Daointerface UserDao { @Query("SELECT * FROM user") fun getAll(): LiveData<List<User>> @Insert suspend fun insert(user: User)}@Database(entities = [User::class], version = 1)abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao}