From c8ee7f7b44c80f0f5e71440318d166f05902a330 Mon Sep 17 00:00:00 2001 From: meyou <2636699780@qq.com> Date: Mon, 18 May 2026 23:08:12 +0800 Subject: [PATCH] =?UTF-8?q?DayCell=20SolarDay=20=E9=9D=99=E6=80=81?= =?UTF-8?q?=E7=BC=93=E5=AD=98=EF=BC=9A=E9=81=BF=E5=85=8D=20Pager=20?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E6=97=B6=E9=87=8D=E5=A4=8D=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E8=A7=A6=E5=8F=91=20GC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 每个 DayCell 创建时调用两次 SolarDay.fromYmd() 计算节日/农历信息。 Pager 缓存页的大量 DayCell 同时重建时产生大量临时对象,加剧 GC 压力 (trace 中 Background concurrent mark compact GC 346ms+253ms)。 修复:在 DayCell.kt 中增加进程级静态缓存 dayCellInfoCache,按日期缓存 computeDayCellInfo() 的结果。首次计算后永久复用,消除重复对象创建。 --- .../kotlin/plus/rua/project/ui/DayCell.kt | 85 ++++++++++--------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/shared/src/commonMain/kotlin/plus/rua/project/ui/DayCell.kt b/shared/src/commonMain/kotlin/plus/rua/project/ui/DayCell.kt index d12570d..a8071a4 100644 --- a/shared/src/commonMain/kotlin/plus/rua/project/ui/DayCell.kt +++ b/shared/src/commonMain/kotlin/plus/rua/project/ui/DayCell.kt @@ -38,6 +38,44 @@ import com.tyme.solar.SolarDay import kotlinx.datetime.LocalDate import plus.rua.project.ShiftKind +// P0-C: 静态缓存 SolarDay 计算结果,避免 Pager 滑动/切换时重复创建对象触发 GC +@Suppress("DEPRECATION") // monthNumber 无替代 API +private fun computeDayCellInfo(date: LocalDate): Triple { + val solarDay = SolarDay.fromYmd(date.year, date.monthNumber, date.day) + val holidayBadge = solarDay.getLegalHoliday()?.let { if (it.isWork()) "班" else "休" } + val lunarDay = solarDay.getLunarDay() + + // 农历传统节日(仅当天) + val lunarFestival = lunarDay.getFestival() + if (lunarFestival != null) { + return Triple(lunarFestival.getName(), true, holidayBadge) + } + + // 节气(当天才显示) + val termDay = solarDay.getTermDay() + if (termDay.getDayIndex() == 0) { + return Triple(termDay.getSolarTerm().getName(), true, holidayBadge) + } + + // 公历节日(仅当天) + val solarFestival = solarDay.getFestival() + if (solarFestival != null) { + return Triple(solarFestival.getName(), true, holidayBadge) + } + + // 默认:农历日期 + val name = lunarDay.getName() + val text = if (name == "初一") { + val lunarMonth = lunarDay.getLunarMonth() + "${lunarMonth.getName()}月" + } else { + name + } + return Triple(text, false, holidayBadge) +} + +private val dayCellInfoCache = mutableMapOf>() + enum class DayCellState { NORMAL, OTHER_MONTH, TODAY, SELECTED, SELECTED_TODAY } @@ -124,53 +162,16 @@ fun DayCell( val selectedOutlineColor = MaterialTheme.colorScheme.primary - data class DayAnnotation(val text: String, val isHighlight: Boolean) - - val holidayBadge = remember(date) { - @Suppress("DEPRECATION") // monthNumber 无替代 API - val solarDay = SolarDay.fromYmd(date.year, date.monthNumber, date.day) - solarDay.getLegalHoliday()?.let { if (it.isWork()) "班" else "休" } - } - - val annotation = remember(date) { - @Suppress("DEPRECATION") // monthNumber 无替代 API - val solarDay = SolarDay.fromYmd(date.year, date.monthNumber, date.day) - val lunarDay = solarDay.getLunarDay() - - // 农历传统节日(仅当天) - val lunarFestival = lunarDay.getFestival() - if (lunarFestival != null) { - return@remember DayAnnotation(lunarFestival.getName(), true) - } - - // 节气(当天才显示) - val termDay = solarDay.getTermDay() - if (termDay.getDayIndex() == 0) { - return@remember DayAnnotation(termDay.getSolarTerm().getName(), true) - } - - // 公历节日(仅当天) - val solarFestival = solarDay.getFestival() - if (solarFestival != null) { - return@remember DayAnnotation(solarFestival.getName(), true) - } - - // 默认:农历日期 - val name = lunarDay.getName() - val text = if (name == "初一") { - val lunarMonth = lunarDay.getLunarMonth() - "${lunarMonth.getName()}月" - } else { - name - } - DayAnnotation(text, false) + // P0-C: 使用静态缓存避免每次重组时重复创建 SolarDay 对象 + val (annotationText, isAnnotationHighlight, holidayBadge) = remember(date) { + dayCellInfoCache.getOrPut(date) { computeDayCellInfo(date) } } val lunarColor by transition.animateColor( transitionSpec = { tween(150, easing = FastOutSlowInEasing) }, label = "lunarColor" ) { state -> - if (annotation.isHighlight) { + if (isAnnotationHighlight) { when (state) { DayCellState.SELECTED_TODAY -> MaterialTheme.colorScheme.onPrimaryContainer.copy( alpha = 0.85f @@ -250,7 +251,7 @@ fun DayCell( style = MaterialTheme.typography.bodyMedium ) Text( - text = annotation.text, + text = annotationText, textAlign = TextAlign.Center, color = lunarColor, fontSize = 7.sp,