Skip to content

Commit 917fa55

Browse files
committed
perf: delete the wrapper key function of rememberSaveable (#1322)
1 parent 5fb7ae1 commit 917fa55

File tree

2 files changed

+32
-13
lines changed

2 files changed

+32
-13
lines changed

app/src/main/kotlin/li/songe/gkd/service/EventService.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import androidx.compose.runtime.LaunchedEffect
2626
import androidx.compose.runtime.SideEffect
2727
import androidx.compose.runtime.collectAsState
2828
import androidx.compose.runtime.getValue
29-
import androidx.compose.runtime.key
3029
import androidx.compose.runtime.mutableIntStateOf
3130
import androidx.compose.runtime.mutableStateListOf
3231
import androidx.compose.runtime.remember
@@ -73,7 +72,8 @@ class EventService : OverlayWindowService(positionKey = "event") {
7372
CompositionLocalProvider(
7473
LocalContentColor provides contentColorFor(bgColor),
7574
) {
76-
val listState = key(eventLogs.isEmpty()) { rememberLazyListState() }
75+
val listState = rememberLazyListState()
76+
LaunchedEffect(eventLogs.isEmpty()) { listState.scrollToItem(0) }
7777
val isAtBottom by listState.isAtBottom()
7878
val subScope = rememberCoroutineScope()
7979
SideEffect {

app/src/main/kotlin/li/songe/gkd/ui/component/Hooks.kt

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package li.songe.gkd.ui.component
22

33
import androidx.compose.animation.core.AnimationConstants.DefaultDurationMillis
44
import androidx.compose.foundation.ScrollState
5+
import androidx.compose.foundation.gestures.ScrollableState
56
import androidx.compose.foundation.layout.height
67
import androidx.compose.foundation.layout.width
78
import androidx.compose.foundation.lazy.LazyListState
@@ -15,7 +16,6 @@ import androidx.compose.runtime.LaunchedEffect
1516
import androidx.compose.runtime.ReadOnlyComposable
1617
import androidx.compose.runtime.collectAsState
1718
import androidx.compose.runtime.derivedStateOf
18-
import androidx.compose.runtime.key
1919
import androidx.compose.runtime.remember
2020
import androidx.compose.runtime.rememberCoroutineScope
2121
import androidx.compose.ui.Modifier
@@ -74,32 +74,51 @@ private fun getCompatStateValue(v: Any?): Any? = when (v) {
7474
else -> v
7575
}
7676

77-
// key 函数的依赖变化时, compose 将重置 key 函数那行代码之后所有代码的状态, 因此需要需要将 key 作用域限定在 Composable fun 内
78-
// 所有的 key 参数必须使用 rememberSaveable 或者 viewModel 来保存状态, 以保证正确的 restore 顺序,否则触发 ClassCastException
7977
@Composable
8078
fun useListScrollState(
8179
v1: Any?,
8280
v2: Any? = null,
8381
v3: Any? = null,
8482
canScroll: () -> Boolean = { true },
8583
): Pair<TopAppBarScrollBehavior, LazyListState> {
86-
return key(
87-
getCompatStateValue(v1),
88-
getCompatStateValue(v2),
89-
getCompatStateValue(v3),
90-
) {
91-
TopAppBarDefaults.enterAlwaysScrollBehavior(canScroll = canScroll) to rememberLazyListState()
84+
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(canScroll = canScroll)
85+
val scrollState = rememberLazyListState()
86+
LaunchedEffect(getCompatStateValue(v1), getCompatStateValue(v2), getCompatStateValue(v3)) {
87+
resetScroll(scrollBehavior, scrollState)
9288
}
89+
return scrollBehavior to scrollState
9390
}
9491

9592
@Composable
9693
fun usePinnedScrollBehaviorState(v1: Any?): Pair<TopAppBarScrollBehavior, LazyListState> {
97-
return key(getCompatStateValue(v1)) { TopAppBarDefaults.pinnedScrollBehavior() to rememberLazyListState() }
94+
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
95+
val scrollState = rememberLazyListState()
96+
LaunchedEffect(getCompatStateValue(v1)) {
97+
resetScroll(scrollBehavior, scrollState)
98+
}
99+
return scrollBehavior to scrollState
98100
}
99101

100102
@Composable
101103
fun useScrollBehaviorState(v1: Any?): Pair<TopAppBarScrollBehavior, ScrollState> {
102-
return key(getCompatStateValue(v1)) { TopAppBarDefaults.enterAlwaysScrollBehavior() to rememberScrollState() }
104+
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
105+
val scrollState = rememberScrollState()
106+
LaunchedEffect(getCompatStateValue(v1)) {
107+
resetScroll(scrollBehavior, scrollState)
108+
}
109+
return scrollBehavior to scrollState
110+
}
111+
112+
private suspend fun resetScroll(
113+
scrollBehavior: TopAppBarScrollBehavior,
114+
scrollState: ScrollableState,
115+
) {
116+
when (scrollState) {
117+
is LazyListState -> scrollState.scrollToItem(0)
118+
is ScrollState -> scrollState.scrollTo(0)
119+
}
120+
scrollBehavior.state.heightOffset = 0f
121+
scrollBehavior.state.contentOffset = 0f
103122
}
104123

105124
@Composable

0 commit comments

Comments
 (0)