从不同Activity启动ThreadActivity时SharedPreferences失效问题
我有一个ThreadActivity,包含saveContact和loadContact两个函数,均通过SharedPreferences配合Gson存储/读取SimpleContact对象组成的ArrayList。保存后立即加载正常,但关闭Activity重新打开时,从特定页面启动无法读取SharedPreferences中的数据——两个Activity都能打开ThreadActivity,其中一个启动完全正常,另一个启动时读取到的数据为空。
保存函数
private fun saveContact() { val gson = Gson() val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext) try { val editor = sharedPreferences.edit() val json = gson.toJson(participants) editor.putString(threadId.toString()+"_Contact", json) editor.apply() } catch(e: Exception) { e.printStackTrace() } }
加载函数
private fun loadContact() { val gson = Gson() val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext) val type = object : TypeToken<ArrayList<SimpleContact?>>() {}.type try { val json = sharedPreferences.getString(threadId.toString()+"_Contact", "") participants = gson.fromJson(json, type) } catch(e: Exception) { e.printStackTrace() } }
可正常启动ThreadActivity的代码
private fun launchThreadActivity(phoneNumber: String, name: String) { hideKeyboard() val text = intent.getStringExtra(Intent.EXTRA_TEXT) ?: "" val numbers = phoneNumber.split(";") val number = if (numbers.size == 1) phoneNumber else Gson().toJson(numbers) Intent(this, ThreadActivity::class.java).apply { putExtra(THREAD_ID, getThreadId(numbers)) putExtra(THREAD_TITLE, name) putExtra(THREAD_TEXT, text) putExtra(THREAD_NUMBER, number) if (intent.action == Intent.ACTION_SEND && intent.extras?.containsKey(Intent.EXTRA_STREAM) == true) { val uri = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM) putExtra(THREAD_ATTACHMENT_URI, uri?.toString()) } else if (intent.action == Intent.ACTION_SEND_MULTIPLE && intent.extras?.containsKey(Intent.EXTRA_STREAM) == true) { val uris = intent.getParcelableArrayListExtra<Uri>(Intent.EXTRA_STREAM) putExtra(THREAD_ATTACHMENT_URIS, uris) } startActivity(this) } }
无法正常启动(读取数据为空)的代码
Intent(this, ThreadActivity::class.java).apply { putExtra(THREAD_ID, (it as Conversation).threadId) putExtra(THREAD_TITLE, it.title) putExtra("fromMain", true) startActivity(this) }
问题分析与解决方案
核心问题大概率是两种启动方式传入的THREAD_ID不一致,导致存储和读取时使用的SharedPreferences键名不匹配:
- 正常启动时通过
getThreadId(numbers)生成ID,异常启动时直接传入Conversation.threadId,两者的生成逻辑或数据类型可能不同(比如一个是String,一个是Long,toString后格式有差异)。 - 加载时如果
threadId为空或与存储时的键名不匹配,就会读取到默认空字符串,Gson解析后得到null或空列表。
修复步骤:
统一
THREAD_ID的生成与传递逻辑
检查getThreadId(numbers)的实现,确保异常启动时传入的Conversation.threadId与该函数生成的ID完全一致(包括数据类型、字符串格式)。比如如果getThreadId返回的是字符串,那么Conversation.threadId也要转为相同格式的字符串再传递。添加
threadId非空校验
在saveContact和loadContact中先判断threadId是否有效,避免使用空值生成无效键名:private fun saveContact() { val threadIdStr = threadId?.toString() ?: return // 空则直接返回 val gson = Gson() val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext) try { val editor = sharedPreferences.edit() val json = gson.toJson(participants) editor.putString("$threadIdStr_Contact", json) editor.apply() } catch(e: Exception) { e.printStackTrace() } }调试阶段验证写入同步
apply()是异步提交,调试时可临时换成commit()确认数据是否同步写入(线上仍推荐用apply()):editor.commit() // 替换editor.apply()检查
SimpleContact序列化有效性
确保SimpleContact类是可被Gson正常序列化的:- 避免内部非静态匿名类
- 字段需为public,或添加
@SerializedName注解配合getter/setter - 若有继承关系,父类也需满足序列化要求
内容的提问来源于stack exchange,提问作者Markusbug
相关产品推荐
相关产品推荐

