Android 10以下版本ClassCastException崩溃问题求助
问题描述
应用在Android 10以下版本频繁崩溃,崩溃提示:Unable to start activity ComponentInfo{OnboardingActivity}: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[]
栈追踪信息:
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Object[] android.util.ArrayMap.allocArrays(ArrayMap.java:213) android.util.ArrayMap.put(ArrayMap.java:499) android.app.ContextImpl.getSharedPreferences(ContextImpl.java:373) com.common.sale.base.CommonPreferences.<init>(CommonPreferences.java:6) com.common.sale.base.BaseActivity.attachBaseContext(BaseActivity.kt:6)
上下文信息:OnboardingActivity继承自BaseActivity,CommonPreferences核心代码如下:
class CommonPreferences(context: Context) { private val SHARED_PREF_ADS: String = "common-project-shared-preference" private val sharedPreferences = context.getSharedPreferences(SHARED_PREF_ADS, Context.MODE_PRIVATE); private val sharedPreferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { _, key -> }.also { sharedPreferences.registerOnSharedPreferenceChangeListener(it) } private val resources = context.resources private val isShowOnboardingKey get() = resources.getString( R.string.preferences_is_show_onboarding_key ) var isShowOnboarding get() = sharedPreferences.getBoolean(isShowOnboardingKey, true) set(value) { sharedPreferences.edit().putBoolean(isShowOnboardingKey, value).apply() } private val appLanguageKey get() = resources.getString( R.string.preferences_app_language_key ) var appLanguage get() = sharedPreferences.getString(appLanguageKey, "") set(value) { sharedPreferences.edit().putString(appLanguageKey, value).apply() } }
崩溃原因
该问题是Android 10及以下版本的系统bug:SharedPreferences内部存储文件损坏,导致ArrayMap解析键值对时,将本应是数组结构的数据错误识别为String,触发强制类型转换失败。
解决方案
1. 主动检测并修复损坏的SharedPreferences文件
在初始化CommonPreferences前,提前尝试获取SharedPreferences并捕获异常,一旦触发ClassCastException就删除损坏的文件,让系统重新生成:
// 修改BaseActivity的attachBaseContext方法 override fun attachBaseContext(newBase: Context?) { super.attachBaseContext(newBase) newBase?.let { ctx -> val prefName = "common-project-shared-preference" try { // 提前触发可能的异常 ctx.getSharedPreferences(prefName, Context.MODE_PRIVATE) } catch (e: ClassCastException) { // 删除损坏的文件 ctx.deleteSharedPreferences(prefName) } // 正常初始化CommonPreferences CommonPreferences(ctx) } }
2. 延迟SharedPreferences初始化时机
attachBaseContext是Context初始化的早期阶段,部分系统资源未完全就绪,建议将CommonPreferences的初始化延迟到onCreate方法中:
// BaseActivity中调整初始化逻辑 lateinit var commonPrefs: CommonPreferences override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) commonPrefs = CommonPreferences(this) }
3. 优化SharedPreferences写入操作
确保写入操作的原子性,避免多线程同时写入导致文件损坏:
- 如果不需要异步写入,改用
commit()替代apply()(commit()是同步操作,保证原子性) - 若必须使用
apply(),确保所有写入调用在同一线程,或通过锁保证线程安全
// 示例:使用commit()保证原子性 sharedPreferences.edit().putBoolean(isShowOnboardingKey, value).commit()
4. 清理旧的损坏缓存
针对Android 10及以下版本,在应用启动时主动检查SharedPreferences文件完整性,发现异常直接删除,避免重复崩溃。
内容的提问来源于stack exchange,提问作者Wendy Nguyen
相关产品推荐
相关产品推荐

