一、核心存储方案概览
Android系统提供了多种数据存储方案,适用于不同场景:
存储方式 | 数据类型 | 容量限制 | 访问权限 | 适用场景 |
---|---|---|---|---|
SharedPreferences | 键值对(简单数据类型) | 小量(<1MB) | 仅应用内部 | 用户偏好设置、简单配置 |
内部存储 | 任意文件 | 应用专属空间 | 仅应用内部 | 私有数据文件、缓存 |
外部存储 | 任意文件 | 设备剩余空间 | 可共享 | 多媒体、文档等公共文件 |
SQLite数据库 | 结构化数据 | 应用专属空间 | 仅应用内部 | 复杂结构化数据存储 |
Room数据库 | 结构化数据(ORM) | 应用专属空间 | 仅应用内部 | 推荐的关系型数据解决方案 |
ContentProvider | 结构化/非结构化数据 | 无硬性限制 | 跨应用共享 | 应用间数据共享 |
网络存储 | 任意数据 | 服务器限制 | 需网络权限 | 云端同步、远程数据 |
二、各存储方案
深度解析
1. SharedPreferences(轻量级键值存储)
实现示例:
// 获取SharedPreferences实例
val sharedPref = context.getSharedPreferences("my_prefs", Context.MODE_PRIVATE)
// 写入数据
sharedPref.edit().apply {
putString("username", "john_doe")
putInt("login_count", 5)
apply() // 异步提交
}
// 读取数据
val username = sharedPref.getString("username", "default")
特点:
-
仅支持基本数据类型:String、Int、Float、Long、Boolean
-
数据以XML格式存储在
/data/data/<package_name>/shared_prefs/
目录 -
线程安全但不支持跨进程
优化建议:
-
大数据量考虑其他方案
-
频繁修改使用
apply()
而非commit()
2. 内部存储(私有文件存储)
文件操作API:
// 写入文件
context.openFileOutput("data.txt", Context.MODE_PRIVATE).use {
it.write("content".toByteArray())
}
// 读取文件
context.openFileInput("data.txt").bufferedReader().useLines { lines ->
lines.forEach { println(it) }
}
存储位置:
/data/data/<package_name>/files/
特点:
-
应用卸载时自动删除
-
无需权限即可使用
-
适合存储敏感信息
3. 外部存储(公共文件存储)
权限声明:
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
文件操作:
// 检查存储可用性
if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
// 获取公共目录
val file = File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS), "myfile.txt")
// 写入文件
file.writeText("Hello World")
}
-
Android 10+强制实施分区存储
-
使用MediaStore或Storage Access Framework(SAF)
4. SQLite数据库
基础用法:
class MyDbHelper(context: Context) : SQLiteOpenHelper(context, "mydb", null, 1) {
override fun onCreate(db: SQLiteDatabase) {
db.execSQL("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)")
}
}
// 使用数据库
val dbHelper = MyDbHelper(context)
val db = dbHelper.writableDatabase
db.insert("users", null, ContentValues().apply {
put("name", "Alice")
})
进阶方案:Room持久化库
// Entity定义
@Entity
data class User(
@PrimaryKey val id: Int,
val name: String
)
// DAO接口
@Dao
interface UserDao {
@Insert
fun insert(user: User)
@Query("SELECT * FROM user")
fun getAll(): List<User>
}
// 数据库类
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
5. ContentProvider(跨应用数据共享)
实现步骤:
-
继承ContentProvider类
-
在AndroidManifest中注册
-
定义URI匹配规则
-
实现CRUD操作
示例URI:
content://com.example.app.provider/users
使用ContentResolver访问:
val cursor = contentResolver.query(
Uri.parse("content://com.example.app.provider/users"),
null, null, null, null
)
三、存储方案选择策略
-
数据敏感性:
-
敏感数据 → 内部存储或加密存储
-
非敏感数据 → 外部存储
-
-
数据结构复杂度:
-
简单键值 → SharedPreferences
-
复杂关系 → Room/SQLite
-
-
共享需求:
-
应用内使用 → 内部存储
-
跨应用共享 → ContentProvider
-
-
数据量大小:
-
小数据 → SharedPreferences
-
大数据 → 文件存储或数据库
-
四、安全最佳实践
-
敏感数据加密:
// 使用Android Keystore系统 val keyGenerator = KeyGenerator.getInstance( KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore") keyGenerator.init(KeyGenParameterSpec.Builder( "my_key", KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()) val secretKey = keyGenerator.generateKey()
-
外部存储验证:
fun isExternalStorageWritable(): Boolean { return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED }
-
数据库安全:
-
使用参数化查询防SQL注入
-
敏感字段考虑加密存储
-
五、性能优化技巧
-
数据库优化:
-
建立合适索引
-
使用事务批量操作
db.beginTransaction() try { // 批量操作 db.setTransactionSuccessful() } finally { db.endTransaction() }
-
-
文件IO优化:
-
使用缓冲流
-
避免主线程操作
-
-
SharedPreferences优化:
-
分组存储代替超大文件
-
使用apply()异步提交
-
六、现代存储趋势
-
DataStore替代SharedPreferences:
// 偏好DataStore val dataStore: DataStore<Preferences> = context.createDataStore(name = "settings") suspend fun savePreference(key: String, value: Int) { dataStore.edit { preferences -> preferences[intPreferencesKey(key)] = value } }
-
使用文件提供程序(FileProvider):
<provider android:name="androidx.core.content.FileProvider" android:authorities="com.example.app.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
-
分区存储(Scoped Storage)适配:
-
使用MediaStore API访问媒体文件
-
使用SAF(Storage Access Framework)访问文档
-
全面理解Android的各种数据存储方案及其适用场景,开发者可以为应用选择最合适的存储策略,确保数据安全、高效地存储和访问。