肝货Android 持久化技术全解SharedPreference 文件存储实战一本通目录什么是持久化Android 持久化方式一览SharedPreference 详解文件存储详解内部存储 vs 外部存储实战代码演示注意事项与最佳实践1. 什么是持久化概念持久化是将数据存储到非易失性存储断电后数据不丢失中。内存易失性程序运行时使用断电丢失 ↓ 持久化 磁盘非易失性数据永久保存手机关机再开机后数据还在 → 持久化成功2. Android 持久化方式一览方式适用场景数据量速度SharedPreference键值对、设置项小快文件存储文本、大数据大较慢SQLite 数据库结构化数据大量中Room复杂查询大量快封装后ContentProvider数据共享不限中DataStore替代 SharedPreference小-中快3. SharedPreference 详解3.1 什么是 SharedPreference用于存储键值对数据的轻量级存储方式适合保存配置、状态等小数据。3.2 基本使用// 获取 SharedPreference 对象valprefsgetSharedPreferences(my_prefs,Context.MODE_PRIVATE)// 保存数据prefs.edit().apply{putString(username,张三)putInt(age,25)putBoolean(isLogin,true)apply()// 异步保存// 或 commit() 同步保存返回 boolean}// 读取数据valusernameprefs.getString(username,默认值)valageprefs.getInt(age,0)valisLoginprefs.getBoolean(isLogin,false)3.3 两种获取方式// 方式1指定名称一个应用可以有多个 Prefs 文件valprefs1getSharedPreferences(user_prefs,Context.MODE_PRIVATE)valprefs2getSharedPreferences(app_settings,Context.MODE_PRIVATE)// 方式2Activity 私有自动使用 Activity 名称作为文件名valprefsgetPreferences(Context.MODE_PRIVATE)3.4 MODE modes存储模式模式说明MODE_PRIVATE只有本应用可访问最常用MODE_WORLD_READABLE其他应用可读已废弃MODE_WORLD_WRITABLE其他应用可写已废弃MODE_MULTI_PROCESS多进程访问不推荐3.5 apply vs commit对比apply()commit()返回值voidboolean是否成功执行方式异步同步性能更快稍慢安全性丢失的机会更小写入更安全推荐大多数情况用apply()如果需要知道写入结果再用commit()。4. 文件存储详解4.1 内部存储文件存储在应用私有目录下其他应用无法访问。// 保存到内部存储valcontentHello WorldvalfileNametest.txtvalfosopenFileOutput(fileName,Context.MODE_PRIVATE)fos.write(content.toByteArray())fos.close()// 读取内部存储valfisopenFileInput(fileName)valbytesByteArray(fis.available())fis.read(bytes)fis.close()valcontentString(bytes)4.2 内部存储目录// 获取各种目录filesDir// /data/data/package/filescacheDir// /data/data/package/cachefilesDir.path// 查看路径// 文件操作valfileFile(filesDir,test.txt)file.writeText(Hello)valcontentfile.readText()4.3 外部存储需要权限且可能不可用SD 卡拔出、存储满。// 外部存储路径valexternalFilesDirgetExternalFilesDir(null)// /storage/emulated/0/Android/data/package/files// 检查外部存储是否可用funisExternalStorageWritable():Boolean{returnEnvironment.getExternalStorageState()Environment.MEDIA_MOUNTED}4.4 权限说明!-- Android 10 外部存储需要权限部分场景--uses-permissionandroid:nameandroid.permission.WRITE_EXTERNAL_STORAGE/uses-permissionandroid:nameandroid.permission.READ_EXTERNAL_STORAGE/!-- Android 13 使用 MediaStore API 访问媒体文件 --5. 内部存储 vs 外部存储对比内部存储外部存储路径/data/data/package/files//storage/.../Android/data/package/files/访问权限本应用私有其他应用不可访问可被其他应用读取卸载应用数据被删除Android 10 部分被删除容量有限但有保证受限于设备存储空间速度较快较慢需要权限不需要需要某些场景6. 实战代码演示6.1 SharedPreference 完整示例classPersistenceActivity:AppCompatActivity(){companionobject{constvalPREFS_NAMEmy_prefsconstvalKEY_USERNAMEusernameconstvalKEY_PASSWORDpassword}privatelateinitvaretUsername:EditTextprivatelateinitvaretPassword:EditTextoverridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_persistence)// 保存数据funsaveToSharedPreference(){valusernameetUsername.text.toString()valpasswordetPassword.text.toString()valprefsgetSharedPreferences(PREFS_NAME,Context.MODE_PRIVATE)prefs.edit().apply{putString(KEY_USERNAME,username)putString(KEY_PASSWORD,password)apply()}}// 读取数据funloadFromSharedPreference(){valprefsgetSharedPreferences(PREFS_NAME,Context.MODE_PRIVATE)valusernameprefs.getString(KEY_USERNAME,未设置)valpasswordprefs.getString(KEY_PASSWORD,未设置)tvResult.text用户名:$username\n密码:$password}}}6.2 文件存储完整示例companionobject{constvalFILE_NAMEuser_data.txt}// 保存到文件privatefunsaveToFile(username:String,password:String){valcontent用户名:$username\n密码:$passwordtry{valfosopenFileOutput(FILE_NAME,Context.MODE_PRIVATE)fos.write(content.toByteArray())fos.close()Toast.makeText(this,文件保存成功,Toast.LENGTH_SHORT).show()}catch(e:Exception){e.printStackTrace()Toast.makeText(this,保存失败:${e.message},Toast.LENGTH_SHORT).show()}}// 从文件读取privatefunloadFromFile():String{returntry{valfileFile(filesDir,FILE_NAME)if(!file.exists())return文件不存在file.readText()}catch(e:Exception){读取失败:${e.message}}}// 删除文件privatefundeleteFile(){valfileFile(filesDir,FILE_NAME)if(file.exists()){file.delete()}}6.3 工具类封装推荐objectPrefsManager{privateconstvalNAMEapp_prefsfunsaveUser(context:Context,username:String,token:String){context.getSharedPreferences(NAME,Context.MODE_PRIVATE).edit().apply{putString(username,username)putString(token,token)apply()}}fungetUser(context:Context):PairString,String{valprefscontext.getSharedPreferences(NAME,Context.MODE_PRIVATE)returnPair(prefs.getString(username,)?:,prefs.getString(token,)?:)}funclearUser(context:Context){context.getSharedPreferences(NAME,Context.MODE_PRIVATE).edit().clear().apply()}funisLoggedIn(context:Context):Boolean{valprefscontext.getSharedPreferences(NAME,Context.MODE_PRIVATE)returnprefs.getString(token,).isNotEmpty()}}7. 注意事项与最佳实践7.1 SharedPreference 注意事项⚠️ 不要存储大量数据 1MB ⚠️ 不要存储敏感信息Token 等加密后存储 ⚠️ MODE_MULTI_PROCESS 不推荐线程不安全 ⚠️ 频繁修改同一个 key 性能差优化建议// ❌ 错误频繁修改repeat(100){prefs.edit().putInt(count,it).apply()}// ✅ 正确批量修改prefs.edit().apply{repeat(100){putInt(count_$it,it)}}7.2 文件存储注意事项⚠️ 外部存储需要权限 ⚠️ 存储前检查空间是否足够 ⚠️ 大文件使用缓冲流 ⚠️ 操作在后台线程执行7.3 数据安全建议// 如果必须存储敏感信息使用 EncryptedSharedPreferencevalmasterKeyMasterKey.Builder(context).setKeyScheme(MasterKey.KeyScheme.AES256_GCM).build()valprefsEncryptedSharedPreferences.create(context,secure_prefs,masterKey,EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM)7.4 选择存储方式场景推荐方式用户设置、登录状态SharedPreference简单文本数据文件存储结构化数据Room/SQLite大量数据Room跨应用共享ContentProvider替代 SharedPreferenceDataStore总结持久化是将数据保存到磁盘断电后不丢失SharedPreference适合存储键值对设置、登录状态文件存储适合存储大量文本或二进制数据内部存储本应用私有不需要权限外部存储需要权限可被其他应用访问安全敏感信息用 EncryptedSharedPreference 或加密