首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android SQLite 存儲大文件(圖片/音頻)最佳實踐:路徑引用而非 Blob

     編輯:程式設計綜合問答

許多 Android 開發者初學時會嘗試將圖片、音頻轉為 `byte[]` 直接存入 SQLite 的 BLOB 字段。雖然技術上可行,但**強烈不推薦**用於生產環境。本文分析缺點並給出行業標準做法:文件落地存儲 + 數據庫存路徑。

為什麼不建議存 BLOB?

缺點影響
數據庫體積膨脹SQLite 單文件建議不超過 100-200MB,大文件快速達到上限,導致讀寫性能驟降、備份困難。
內存壓力大讀取 BLOB 需一次性加載到內存 (`Cursor.getBlob()`),易導致 OOM,尤其對大圖/長音頻。
事務開銷高寫入大 Blob 會長時間鎖定數據庫,阻塞其他查詢。
無法利用系統優化無法使用 `BitmapFactory.decodeFile` 采樣加載、MediaPlayer 直接播放文件路徑、Glide/Picasso 緩存機制等成熟方案。

最佳實踐:文件系統 + 路徑引用

1. 文件存儲位置選擇

  • 內部存儲 (`context.getFilesDir()` / `getCacheDir()`): 私有,應用卸載自動刪除,適合敏感/臨時文件。
  • 外部存儲公共目錄 (`Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)`): 可被用戶/其他應用訪問(需 `READ_EXTERNAL_STORAGE` 權限),適合相冊、音樂等共享內容。
    **Android 10+ (API 29) 建議使用 MediaStore API 插入媒體,獲取 `content://` Uri,無需權限即可讀寫。
  • 外部存儲私有目錄 (`context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)`): 不需權限(API 19+),應用卸載自動刪除,適合不想共享的大文件。

2. 數據庫表設計

CREATE TABLE media (
    _id INTEGER PRIMARY KEY AUTOINCREMENT,
    type TEXT NOT NULL,           -- 'image' / 'audio'
    mime_type TEXT,               -- 'image/jpeg', 'audio/mpeg'
    file_path TEXT NOT NULL,      -- 存儲文件絕對路徑 或 content:// Uri
    file_size INTEGER,
    duration INTEGER,             -- 音頻時長(ms)
    width INTEGER, height INTEGER,-- 圖片尺寸
    created_at INTEGER DEFAULT (strftime('%s','now'))
);

3. 存儲流程示例(圖片)

// 1. 保存文件到內部存儲
File dir = new File(context.getFilesDir(), "images");
if (!dir.exists()) dir.mkdirs();
File imageFile = new File(dir, "IMG_" + System.currentTimeMillis() + ".jpg");

try (FileOutputStream fos = new FileOutputStream(imageFile)) {
    bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
}

// 2. 插入數據庫記錄路徑
ContentValues values = new ContentValues();
values.put("type", "image");
values.put("mime_type", "image/jpeg");
values.put("file_path", imageFile.getAbsolutePath()); // 或 Uri.toString()
values.put("file_size", imageFile.length());
values.put("width", bitmap.getWidth());
values.put("height", bitmap.getHeight());
db.insert("media", null, values);

4. 讀取與顯示

// 查詢路徑
String path = cursor.getString(cursor.getColumnIndex("file_path"));

// 圖片:使用 Glide/Picasso 直接加載路徑,自動處理緩存、采樣、生命周期
Glide.with(context).load(new File(path)).into(imageView);

// 音頻:MediaPlayer 直接設置數據源
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(path);
mp.prepareAsync(); // 異步準備

特殊場景:極小圖標/縮略圖

若文件極小(< 10-20KB),如用戶頭像縮略圖、狀態圖標,**可考慮存 BLOB**,避免大量小文件 IO 開銷。但仍建議設置上限並評估總量。

總結

**大文件落盤,路徑入庫** 是 Android 存儲鐵律。善用文件系統與媒體庫 API,您的應用將更輕量、高效、穩定。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved