16人参与 • 2025-06-22 • Android
当应用需要在多个进程间共享数据时,sharedpreferences的默认实现存在严重缺陷:
// 传统sharedpreferences在多进程环境下的问题示例 val sharedpref = getsharedpreferences("my_prefs", context.mode_private) // 进程a写入数据 sharedpref.edit().putstring("key", "value_from_process_a").apply() // 进程b读取数据 - 可能读取到旧值或null val value = sharedpref.getstring("key", "default")
问题根源在于:
apply()
异步写入导致同步延迟方案 | 实现难度 | 性能 | 可靠性 | 适用场景 |
---|---|---|---|---|
mode_multi_process | ★☆☆ | ★★☆ | ★☆☆ | android 3.0以下系统 |
contentprovider | ★★★ | ★★☆ | ★★★ | 需要精细控制的数据共享 |
mmkv | ★☆☆ | ★★★ | ★★★ | 高性能多进程数据共享 |
文件锁 | ★★☆ | ★☆☆ | ★★☆ | 简单键值对同步 |
通过contentprovider实现跨进程数据访问:
class sharedprefprovider : contentprovider() { companion object { const val authority = "com.example.provider.sharedpref" val content_uri = uri.parse("content://$authority/prefs") } private lateinit var sharedpref: sharedpreferences override fun oncreate(): boolean { sharedpref = context!!.getsharedpreferences( "multi_process_prefs", context.mode_private ) return true } override fun insert(uri: uri, values: contentvalues?): uri? { values?.let { val key = it.getasstring("key") val value = it.getasstring("value") sharedpref.edit().putstring(key, value).commit() } return uri } override fun query( uri: uri, projection: array<string>?, selection: string?, selectionargs: array<string>?, sortorder: string? ): cursor? { val key = selectionargs?.getornull(0) ?: return null val value = sharedpref.getstring(key, null) ?: return null return matrixcursor(arrayof("value")).apply { addrow(arrayof(value)) } } // 更新数据实现 override fun update( uri: uri, values: contentvalues?, selection: string?, selectionargs: array<string>? ): int { values?.let { val key = it.getasstring("key") val newvalue = it.getasstring("value") sharedpref.edit().putstring(key, newvalue).commit() return 1 } return 0 } // 删除数据实现 override fun delete(uri: uri, selection: string?, selectionargs: array<string>?): int { selectionargs?.getornull(0)?.let { key -> if (sharedpref.contains(key)) { sharedpref.edit().remove(key).commit() return 1 } } return 0 } override fun gettype(uri: uri): string? = null }
注册contentprovider:
<application> <provider android:name=".sharedprefprovider" android:authorities="com.example.provider.sharedpref" android:exported="true" android:process=":remote" /> </application>
跨进程读写操作:
// 写入数据 fun savedata(key: string, value: string) { val values = contentvalues().apply { put("key", key) put("value", value) } context.contentresolver.insert(sharedprefprovider.content_uri, values) } // 读取数据 fun getdata(key: string): string? { return try { val cursor = context.contentresolver.query( sharedprefprovider.content_uri, null, "key = ?", arrayof(key), null ) cursor?.use { if (it.movetofirst()) { it.getstring(it.getcolumnindex("value")) } else null } } catch (e: exception) { null } }
腾讯开源的mmkv是解决多进程数据共享的最佳方案:
添加依赖:
dependencies { implementation 'com.tencent:mmkv:1.3.4' }
初始化:
class myapp : application() { override fun oncreate() { super.oncreate() val rootdir = mmkv.initialize(this) log.i("mmkv", "初始化路径: $rootdir") } }
多进程读写操作:
// 获取mmkv实例(多进程模式) private val kv: mmkv by lazy { mmkv.mmkvwithid("inter_process_kv", mmkv.multi_process_mode) } // 写入数据 fun saveuserinfo(user: user) { kv.encode("user_name", user.name) kv.encode("user_age", user.age) kv.encode("user_vip", user.isvip) } // 读取数据 fun getuserinfo(): user? { return if (kv.contains("user_name")) { user( name = kv.decodestring("user_name") ?: "", age = kv.decodeint("user_age", 0), isvip = kv.decodebool("user_vip", false) ) } else null } // 删除数据 fun clearuserinfo() { kv.remove("user_name") kv.remove("user_age") kv.remove("user_vip") }
对于简单场景,可以使用文件锁实现基本同步:
class filelockhelper(context: context) { private val lockfile = file(context.filesdir, "prefs_lock") private val channel by lazy { randomaccessfile(lockfile, "rw").channel } @synchronized fun <t> withlock(block: () -> t): t { val lock = channel.lock() return try { block() } finally { lock.release() } } } // 使用示例 val lockhelper = filelockhelper(context) fun savedata(key: string, value: string) { lockhelper.withlock { val prefs = getsharedpreferences("locked_prefs", mode_private) prefs.edit().putstring(key, value).commit() } } fun getdata(key: string): string? { return lockhelper.withlock { val prefs = getsharedpreferences("locked_prefs", mode_private) prefs.getstring(key, null) } }
选型建议:
1.批量写入优化:
// mmkv批量写入示例 kv.edit().apply { putstring("name", "john") putint("age", 30) putboolean("vip", true) commit() }
2.数据压缩策略:
// 存储json等结构化数据 val userjson = gson().tojson(user) kv.encode("user_data", userjson) // 读取时 val json = kv.decodestring("user_data") val user = gson().fromjson(json, user::class.java)
3.敏感数据加密:
// 使用mmkv加密敏感数据 val cryptkey = "mysecretkey01".tobytearray() val securekv = mmkv.mmkvwithid("secure_kv", mmkv.multi_process_mode, cryptkey)
jetpack datastore是google推荐的sharedpreferences替代方案:
dependencies { implementation "androidx.datastore:datastore-preferences:1.0.0" }
// 创建datastore val context.datastore by preferencesdatastore(name = "settings") // 写入数据 suspend fun savesettings(isdarkmode: boolean) { context.datastore.edit { preferences -> preferences[preferenceskeys.booleankey("dark_mode")] = isdarkmode } } // 读取数据 val darkmodeflow: flow<boolean> = context.datastore.data .map { preferences -> preferences[preferenceskeys.booleankey("dark_mode")] ?: false }
注意:datastore目前不支持多进程,但可以结合本文方案实现多进程同步
在多进程android应用中,sharedpreferences已不再是数据共享的最佳选择。本文介绍的mmkv和contentprovider方案提供了更可靠、高效的解决方案。建议开发者根据具体场景选择合适的技术方案:
通过合理选择技术方案,开发者可以彻底解决android多进程数据共享的难题,构建更稳定高效的应用程序。
到此这篇关于android实现多进程数据共享的方法解析的文章就介绍到这了,更多相关android多进程数据共享内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论