LocaleList初始化抛出IllegalArgumentException:list[1]重复致应用崩溃求助
核心原因定位
从堆栈信息来看,崩溃根源是java.lang.IllegalArgumentException: list[1] is a repetition——系统在初始化LocaleList时发现列表里有重复的语言项。这个问题出现在AppCompat框架合并系统与应用自定义Locale的过程中,恰好和你怀疑的Bottom Sheet Dialog触发时机吻合:当BottomSheetDialogFragment创建Dialog实例时,AppCompatDelegate会重新计算应用的Locale列表,若此时列表存在重复项,就会触发崩溃。
可能的触发场景
- 语言切换逻辑有漏洞:设置应用Locale时未做去重处理,导致列表里出现重复的语言项(比如重复添加同一Locale,或同时添加
es和es-ES这类关联但重复的项) - 系统Locale叠加冲突:部分设备的系统语言设置和应用自定义Locale叠加后,AppCompat的合并逻辑未处理重复项
- 并发修改Locale:Bottom Sheet显示的同时,有其他线程在修改应用Locale,导致Locale列表处于不一致状态
修复方案
Locale设置时强制去重
在设置应用Locale的代码里,对要添加的Locale列表做去重处理,示例代码:List<Locale> localeList = new ArrayList<>(Arrays.asList(Locale.ENGLISH, new Locale("es"), new Locale("bg"))); // 用LinkedHashSet去重,保留原有顺序 Set<Locale> uniqueLocales = new LinkedHashSet<>(localeList); LocaleList finalLocaleList = new LocaleList(uniqueLocales.toArray(new Locale[0])); AppCompatDelegate.setApplicationLocales(finalLocaleList);升级AppCompat库版本
这个问题大概率是AppCompat的已知bug,检查你的依赖版本,升级到最新稳定版(比如androidx.appcompat:appcompat:1.6.1及以上),新版本可能修复了Locale合并时的去重逻辑漏洞。避免并发修改Locale
确保Bottom Sheet Dialog显示前后,没有其他线程在修改应用Locale。可以将Locale修改操作放在主线程执行,或者加锁避免并发冲突。自定义BottomSheetDialog绕过自动合并
如果上述方法无效,可重写BottomSheetDialog的初始化逻辑,手动设置Locale:public class CustomBottomSheetDialog extends BottomSheetDialog { public CustomBottomSheetDialog(@NonNull Context context) { super(context); // 手动设置目标Locale Locale desiredLocale = ...; // 替换为你的应用当前Locale Configuration config = new Configuration(context.getResources().getConfiguration()); config.setLocale(desiredLocale); Context newContext = context.createConfigurationContext(config); applyOverrideConfiguration(config); } }然后在BottomSheetDialogFragment中使用自定义Dialog:
@NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { return new CustomBottomSheetDialog(requireContext()); }
复现建议
虽然你无法自行复现,可尝试以下场景模拟:
- 切换语言后立即触发Bottom Sheet显示
- 在系统语言与应用语言一致的设备上测试(比如系统设为西班牙语,应用也切换到西班牙语后打开Bottom Sheet)
- 用Espresso编写测试用例,模拟语言切换和Bottom Sheet显示同时执行的并发场景
内容的提问来源于stack exchange,提问作者shko

