Android Calendar循环add日期时disabledDays仅存入单条日期异常
问题原因
核心问题是你全程只创建了1个可变的Calendar实例,循环过程中所有操作都在修改这同一个对象的内部状态:
- 第一次循环时,你把
dayCalendar对象的引用添加到了disabledDays集合中,此时集合里存的是指向这个唯一实例的引用 - 后续循环调用
dayCalendar.add(Calendar.DAY_OF_MONTH, 1)时,修改的就是这个已经存在于集合中的实例本身的时间值,集合里存的引用指向的对象时间会跟着同步变化 - 执行
!disabledDays.contains(dayCalendar)判断时,因为集合里本来就存了这个对象的引用,判断结果永远为false,不会再执行添加操作,最终集合里只会保留1个元素,且这个元素的时间是循环全部执行完后的最终日期,完全不符合预期。
修复方法
每次循环生成新日期时,都要基于初始时间克隆出一个独立的Calendar实例再操作,确保存入集合的每个对象都是独立的、不会被后续修改的实例。
修复后的代码如下:
val baseCalendar = Calendar.getInstance().apply { time = entryDateC.time } for (day in 1..howManyDays) { // 每次循环克隆新实例,避免复用同一个可变对象 val dayCalendar = (baseCalendar.clone() as Calendar).apply { add(Calendar.DAY_OF_MONTH, day) } if (!disabledDays.contains(dayCalendar)) { disabledDays.add(dayCalendar) } }
如果你使用Java 8+或Android API 26及以上版本,更推荐用不可变的java.time包下的LocalDate类处理日期,从根源上避免可变对象复用导致的这类问题,示例代码:
import java.time.LocalDate import java.time.ZoneId // 先将初始Date类型转换为不可变的LocalDate val baseDate = entryDateC.toInstant() .atZone(ZoneId.systemDefault()) .toLocalDate() for (day in 1..howManyDays) { // plusDays会返回全新的LocalDate实例,不存在复用修改问题 val targetDate = baseDate.plusDays(day.toLong()) if (!disabledDays.contains(targetDate)) { disabledDays.add(targetDate) } }
内容的提问来源于stack exchange,提问作者Mark George
相关产品推荐
相关产品推荐

