From da46204de43fc293002640a61aaa11eef1b66d68 Mon Sep 17 00:00:00 2001 From: xfy Date: Mon, 25 May 2026 16:44:06 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20DayCell=20produceState=20=E4=B8=8A?= =?UTF-8?q?=E7=A7=BB=E5=88=B0=E9=A1=B5=E9=9D=A2=E7=BA=A7=EF=BC=8C=E5=87=8F?= =?UTF-8?q?=E5=B0=91=E5=8D=8F=E7=A8=8B=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CalendarMonthPage 统一预计算整月 42 天的 lunarData(1 个协程), 通过参数传入 DayCell,避免每个单元格独立启动 produceState(42 协程)。 - holidayBadges produceState 扩展为 lunarDataMap,存储完整 DayCellInfo - DayCell 添加可选 lunarData 参数,条件分支调用 DayCellImpl - WeekPager 保持向后兼容(不传 lunarData 时内部获取) Co-Authored-By: Claude Opus 4.7 (1M context) --- .../plus/rua/project/ui/CalendarMonthPage.kt | 23 +++---- .../kotlin/plus/rua/project/ui/DayCell.kt | 60 ++++++++++++++++--- 2 files changed, 66 insertions(+), 17 deletions(-) diff --git a/core/src/main/kotlin/plus/rua/project/ui/CalendarMonthPage.kt b/core/src/main/kotlin/plus/rua/project/ui/CalendarMonthPage.kt index c93af5d..73aca94 100644 --- a/core/src/main/kotlin/plus/rua/project/ui/CalendarMonthPage.kt +++ b/core/src/main/kotlin/plus/rua/project/ui/CalendarMonthPage.kt @@ -25,6 +25,7 @@ import kotlinx.datetime.LocalDate import kotlinx.datetime.minus import kotlinx.datetime.number import kotlinx.datetime.plus +import plus.rua.project.DayCellInfo import plus.rua.project.LunarCache import plus.rua.project.ShiftKind @@ -69,27 +70,26 @@ fun CalendarMonthPage( val density = LocalDensity.current val interactionSource = remember { MutableInteractionSource() } - val holidayBadges by produceState( - initialValue = emptyMap(), + val lunarDataMap by produceState( + initialValue = emptyMap(), key1 = year, key2 = month ) { - val map = mutableMapOf() + val map = mutableMapOf() for (dayData in days) { - val info = LunarCache.default.getOrCompute(dayData.date) - map[dayData.date] = info.holidayBadge + map[dayData.date] = LunarCache.default.getOrCompute(dayData.date) } value = map } - val holidayEdges = remember(holidayBadges, year, month) { + val holidayEdges = remember(lunarDataMap, year, month) { val map = mutableMapOf() for (dayData in days) { val date = dayData.date - val badge = holidayBadges[date] + val badge = lunarDataMap[date]?.holidayBadge if (badge == null) continue - val prevBadge = holidayBadges[date.minus(DatePeriod(days = 1))] - val nextBadge = holidayBadges[date.plus(DatePeriod(days = 1))] + val prevBadge = lunarDataMap[date.minus(DatePeriod(days = 1))]?.holidayBadge + val nextBadge = lunarDataMap[date.plus(DatePeriod(days = 1))]?.holidayBadge map[date] = HolidayEdgeInfo( isStart = prevBadge != badge, isEnd = nextBadge != badge @@ -128,6 +128,7 @@ fun CalendarMonthPage( shiftKindAt = shiftKindAt, showLegalHoliday = showLegalHoliday, holidayEdges = holidayEdges, + lunarDataMap = lunarDataMap, onDateClick = onDateClick, onRowHeightMeasured = onRowHeightMeasured, interactionSource = interactionSource @@ -150,6 +151,7 @@ private fun WeekRow( shiftKindAt: (LocalDate) -> ShiftKind?, showLegalHoliday: Boolean, holidayEdges: Map, + lunarDataMap: Map, onDateClick: (LocalDate) -> Unit, onRowHeightMeasured: ((Int) -> Unit)?, interactionSource: MutableInteractionSource, @@ -235,7 +237,8 @@ private fun WeekRow( holidayEdgeInfo = holidayEdges[dayData.date], onClick = { onDateClick(dayData.date) }, modifier = Modifier.weight(1f), - interactionSource = interactionSource + interactionSource = interactionSource, + lunarData = lunarDataMap[dayData.date] ) } } diff --git a/core/src/main/kotlin/plus/rua/project/ui/DayCell.kt b/core/src/main/kotlin/plus/rua/project/ui/DayCell.kt index bc52234..e64b9d1 100644 --- a/core/src/main/kotlin/plus/rua/project/ui/DayCell.kt +++ b/core/src/main/kotlin/plus/rua/project/ui/DayCell.kt @@ -72,15 +72,61 @@ fun DayCell( onClick: () -> Unit, modifier: Modifier = Modifier, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - lunarCache: LunarCache = LunarCache.default + lunarCache: LunarCache = LunarCache.default, + lunarData: DayCellInfo? = null, ) { - val lunarData by produceState( - initialValue = DayCellInfo("", false, null), - key1 = date, - key2 = lunarCache - ) { - value = lunarCache.getOrCompute(date) + if (lunarData != null) { + DayCellImpl( + date = date, + isCurrentMonth = isCurrentMonth, + isSelected = isSelected, + isToday = isToday, + shiftKind = shiftKind, + showLegalHoliday = showLegalHoliday, + holidayEdgeInfo = holidayEdgeInfo, + onClick = onClick, + modifier = modifier, + interactionSource = interactionSource, + lunarData = lunarData, + ) + } else { + val computed by produceState( + initialValue = DayCellInfo("", false, null), + key1 = date, + key2 = lunarCache + ) { + value = lunarCache.getOrCompute(date) + } + DayCellImpl( + date = date, + isCurrentMonth = isCurrentMonth, + isSelected = isSelected, + isToday = isToday, + shiftKind = shiftKind, + showLegalHoliday = showLegalHoliday, + holidayEdgeInfo = holidayEdgeInfo, + onClick = onClick, + modifier = modifier, + interactionSource = interactionSource, + lunarData = computed, + ) } +} + +@Composable +private fun DayCellImpl( + date: LocalDate, + isCurrentMonth: Boolean, + isSelected: Boolean, + isToday: Boolean, + shiftKind: ShiftKind?, + showLegalHoliday: Boolean, + holidayEdgeInfo: HolidayEdgeInfo?, + onClick: () -> Unit, + modifier: Modifier, + interactionSource: MutableInteractionSource, + lunarData: DayCellInfo, +) { val annotationText = lunarData.annotationText val isAnnotationHighlight = lunarData.isAnnotationHighlight val holidayBadge = lunarData.holidayBadge