在 Android 應用開發中,本地資料管理是構建離線功能、提升使用者體驗的核心環節。SQLite 作為輕量級嵌入式資料庫,憑藉其零配置、事務支援和穩妥查詢能力,成為儲存結構化資料的可選方案。結合報表生成技術,開發者可實現資料視覺化、統計分析及匯出功能,滿足業務監控、使用者行為分析等場景需求。本文將系統講解 SQLite 資料庫的 CRUD 操作、效能最佳化策略,以及如何基於本地資料生成動態報表,助力開發者打造穩定、穩妥的資料驅動型應用。
一、SQLite 資料庫基礎與核心操作
1. SQLite 優勢與適用場景
輕量級:資料庫檔案僅需一個
.db檔案,無需單獨伺服器程序。ACID 相容:支援事務(Transaction),有助於支援資料一致性。
跨平臺:資料檔案可直接在 iOS、Web 等平臺複用。
典型場景:使用者配置儲存、離線快取、本地日誌記錄、小型 CRM 系統。
2. 資料庫建立與表設計
透過
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); }}
3. CRUD 操作實戰
插入資料(Insert)
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}查詢資料(Query)
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;}更新與刪除(Update/Delete)
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)});}二、SQLite 效能最佳化策略
1. 索引最佳化
為高頻查詢欄位新增索引:
java@Overridepublic void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE users (...)"); db.execSQL("CREATE INDEX idx_user_email ON users(email)"); // 加速郵箱查詢}避免過度索引:索引會佔用儲存空間並降低寫入效能,僅在
WHERE、JOIN條件欄位上新增。
2. 批次操作與事務
使用事務包裹批次插入:
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(); // 提交或回滾 }}
3. 查詢最佳化技巧
避免
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 的報表生成實現
1. 報表需求分析
常見型別:銷售趨勢圖、使用者活躍度熱力圖、庫存檔點表。
資料來源:SQLite 查詢結果 + 時間聚合(如按日/月統計)。
輸出格式:
RecyclerView列表、MPAndroidChart圖表、CSV/Excel 匯出。
2. 動態報表生成示例
步驟 1:聚合查詢資料
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;}步驟 2:使用 MPAndroidChart 繪製折線圖
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(); // 重新整理圖表步驟 3:匯出 CSV 檔案
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(); }}四、高階場景與擴充套件
1. 多表關聯查詢
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;}2. 使用 Room 持久化庫(推薦)
優勢:編譯時 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}
線上諮詢
電話諮詢
微信諮詢
回到頂部