Android 12下SimpleDateFormat解析日期排序崩溃问题咨询
问题根因
崩溃由两个兼容性问题共同导致:
- 系统版本日期解析规则差异:Android 7使用旧版ICU库,
zzzz时区模式可兼容解析GMT+10:00这类偏移格式;Android 12升级ICU版本后,zzzz仅匹配长时区名称(如中国标准时间),不再兼容GMT偏移格式,直接触发解析失败。 - 未指定解析Locale:
SimpleDateFormat默认跟随系统语言,若设备为非英文环境,EEE/MMM占位符会尝试匹配本地语言的星期、月份缩写,和传入的英文日期串(Tue、Jun这类英文缩写)完全不匹配,同样会解析失败。
额外隐患:当前代码捕获解析异常后直接抛出运行时异常,没有兜底逻辑,只要单条数据解析失败就会触发整个页面崩溃。
修复方案
方案1:修正SimpleDateFormat配置(无额外依赖,兼容全版本)
调整日期匹配模式、强制指定英文Locale,适配新旧Android版本解析规则:
Collections.sort(collaborationRoomModelList, new Comparator<CollaborationRoomModel>() { // 用z替换zzzz适配GMT偏移格式,强制指定Locale.ENGLISH匹配英文星期/月份缩写 private final DateFormat f = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH); @Override public int compare(CollaborationRoomModel lhs, CollaborationRoomModel rhs) { try { return f.parse(rhs.getDate()).compareTo(f.parse(lhs.getDate())); } catch (ParseException e) { e.printStackTrace(); // 解析失败兜底返回0,避免脏数据导致整体崩溃 return 0; } } });
方案2:使用java.time API(推荐,解析逻辑更稳定)
Android 8.0+内置的java.time包日期解析规则不随系统ICU版本变动出现兼容问题,如果项目开启核心库脱糖可兼容至API 21及以下版本,彻底规避SimpleDateFormat自带的线程不安全、规则随版本变动的坑:
- 先在app模块
build.gradle开启脱糖配置(仅需兼容API<26时配置):
android { compileOptions { coreLibraryDesugaringEnabled true sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' }
- 排序实现代码:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss O yyyy", Locale.ENGLISH); Collections.sort(collaborationRoomModelList, (lhs, rhs) -> { try { OffsetDateTime rhsTime = OffsetDateTime.parse(rhs.getDate(), formatter); OffsetDateTime lhsTime = OffsetDateTime.parse(lhs.getDate(), formatter); return rhsTime.compareTo(lhsTime); } catch (DateTimeParseException e) { e.printStackTrace(); return 0; } });
性能优化建议
不要在compare方法中重复解析日期:列表加载时就把所有日期字符串提前解析为long类型时间戳存入Model,排序时直接比较long值即可,既可以大幅提升排序性能,也能避免排序过程中重复解析触发的异常问题。
内容的提问来源于stack exchange,提问作者TharakaNirmana
相关产品推荐
相关产品推荐

