Skip to content

一、核心持久化方案

1. SharedPreferences

  • 用途:存储简单的键值对(如用户设置、标记位)。
  • 特点:轻量级、XML 格式存储,适合小数据量。
  • 代码示例
    kotlin
    // 获取 SharedPreferences 实例
    val sharedPref = context.getSharedPreferences("MyPrefs", Context.MODE_PRIVATE)
    
    // 写入数据
    sharedPref.edit().apply {
        putString("username", "Alice")
        putInt("score", 100)
        apply() // 异步提交(推荐)
        // commit() 同步提交(可能阻塞主线程)
    }
    
    // 读取数据
    val username = sharedPref.getString("username", "default")
    val score = sharedPref.getInt("score", 0)

2. 文件存储

  • 用途:存储文本、二进制文件(如图片、缓存)。
  • 分类
    • 内部存储:私有目录(/data/data/<包名>/files),无需权限。
    • 外部存储:公共目录(如 Downloads),需 WRITE_EXTERNAL_STORAGE 权限(Android 10+ 需分区存储适配)。

示例代码

kotlin
// 写入内部文件
val fileContent = "Hello, World!"
context.openFileOutput("my_file.txt", Context.MODE_PRIVATE).use {
    it.write(fileContent.toByteArray())
}

// 读取内部文件
context.openFileInput("my_file.txt").use {
    val content = it.bufferedReader().readText()
}

// 写入外部公共目录(需权限)
val imageFile = File(Environment.getExternalStoragePublicDirectory(
    Environment.DIRECTORY_PICTURES), "my_image.jpg")
imageFile.outputStream().use {
    it.write(bitmapBytes)
}

3. SQLite 数据库

  • 用途:存储结构化数据(如用户信息、交易记录)。
  • 原生 APISQLiteOpenHelper,需手动处理 SQL。
  • 代码示例
    kotlin
    class MyDbHelper(context: Context) : SQLiteOpenHelper(context, "my_db", null, 1) {
        override fun onCreate(db: SQLiteDatabase) {
            db.execSQL("CREATE TABLE User (id INTEGER PRIMARY KEY, name TEXT)")
        }
        override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {}
    }
    
    // 插入数据
    val db = MyDbHelper(context).writableDatabase
    db.execSQL("INSERT INTO User (name) VALUES (?)", arrayOf("Alice"))
    
    // 查询数据
    val cursor = db.rawQuery("SELECT * FROM User", null)
    while (cursor.moveToNext()) {
        val name = cursor.getString(cursor.getColumnIndex("name"))
    }
    cursor.close()

4. Room Persistence Library

  • 用途:SQLite 的抽象层,提供编译时 SQL 校验、简化数据库操作。
  • 核心组件
    • @Entity:定义数据表结构。
    • @Dao:数据库操作接口。
    • @Database:数据库持有类。

完整示例

kotlin
// 定义 Entity
@Entity
data class User(
    @PrimaryKey val id: Int,
    val name: String,
    val age: Int
)

// 定义 Dao
@Dao
interface UserDao {
    @Query("SELECT * FROM User")
    fun getAll(): List<User>

    @Insert
    fun insert(user: User)

    @Delete
    fun delete(user: User)
}

// 定义 Database
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

// 初始化数据库
val db = Room.databaseBuilder(
    context,
    AppDatabase::class.java, "my-database"
).build()

// 使用协程异步操作
lifecycleScope.launch {
    val users = withContext(Dispatchers.IO) {
        db.userDao().getAll()
    }
}

5. DataStore

  • 用途:替代 SharedPreferences,支持异步操作、类型安全。
  • 两种实现
    • Preferences DataStore:键值对存储。
    • Proto DataStore:使用 Protobuf 存储结构化数据。

示例代码(Preferences DataStore)

kotlin
// 定义键
val USER_NAME_KEY = preferencesKey<String>("user_name")

// 创建 DataStore
val dataStore = context.createDataStore("settings")

// 写入数据
dataStore.edit { preferences ->
    preferences[USER_NAME_KEY] = "Bob"
}

// 读取数据(返回 Flow)
val userNameFlow: Flow<String> = dataStore.data
    .map { preferences ->
        preferences[USER_NAME_KEY] ?: "default"
    }

二、方案对比与选型

技术适用场景优点缺点
SharedPreferences简单配置项(如开关、用户名)使用简单,轻量级不适合复杂数据,无类型安全
文件存储大文件(图片、日志)、非结构化数据灵活,支持任意格式需手动管理读写,无结构化查询
SQLite复杂结构化数据支持 SQL 查询,成熟稳定需编写 SQL,维护成本高
Room复杂结构化数据编译时校验,与 LiveData/Flow 集成需定义 Entity/Dao,学习曲线略高
DataStore替代 SharedPreferences异步安全,支持协程迁移成本(旧项目需替换 SharedPref)

三、高级技巧与注意事项

1. 数据库迁移(Room)

  • 版本升级时修改表结构
    kotlin
    Room.databaseBuilder(...)
        .addMigrations(object : Migration(1, 2) {
            override fun migrate(database: SupportSQLiteDatabase) {
                database.execSQL("ALTER TABLE User ADD COLUMN email TEXT")
            }
        })
        .build()

2. 加密存储

  • 敏感数据(如令牌、密码)
    • 使用 EncryptedSharedPreferences(Android 6.0+):
      kotlin
      val masterKey = MasterKey.Builder(context)
          .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
          .build()
      
      val sharedPref = EncryptedSharedPreferences.create(
          context,
          "secret_prefs",
          masterKey,
          EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
          EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
      )
    • 数据库加密:使用 SQLCipher 或 Room 加密扩展库。

3. 文件存储最佳实践

  • 缓存文件:使用 context.cacheDir,系统可能自动清理。
  • 分区存储(Android 10+)
    • 访问公共目录需 READ_EXTERNAL_STORAGE 权限。
    • 使用 MediaStoreStorage Access Framework

4. 数据备份

  • Auto Backup:配置 AndroidManifest.xml 自动备份到 Google Drive。
    xml
    <application
        android:allowBackup="true"
        android:fullBackupContent="@xml/backup_rules">
    • 排除特定文件:创建 res/xml/backup_rules.xml

四、完整示例:Room + ViewModel + LiveData

kotlin
// ViewModel
class UserViewModel(application: Application) : AndroidViewModel(application) {
    private val db = Room.databaseBuilder(
        application,
        AppDatabase::class.java, "user-db"
    ).build()

    private val _users = MutableLiveData<List<User>>()
    val users: LiveData<List<User>> = _users

    fun loadUsers() {
        viewModelScope.launch {
            _users.value = withContext(Dispatchers.IO) {
                db.userDao().getAll()
            }
        }
    }

    fun addUser(name: String, age: Int) {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                db.userDao().insert(User(0, name, age))
            }
            loadUsers()
        }
    }
}

// Activity/Fragment 中观察数据
userViewModel.users.observe(this) { users ->
    // 更新 UI
}

五、总结建议

  1. 简单配置:优先使用 DataStore 或 SharedPreferences。
  2. 结构化数据:选择 Room + SQLite,利用类型安全和 LiveData/Flow 响应式支持。
  3. 大文件/媒体:使用文件存储,注意分区存储限制。
  4. 安全敏感数据:务必加密(如 EncryptedSharedPreferences 或 SQLCipher)。
  5. 版本兼容:处理数据库迁移和旧设备适配。

通过合理选择持久化方案,可显著提升应用性能和可维护性。