Cache per-item color schemes in ListState to avoid list jank - #27
Open
patrickunterwegs wants to merge 2 commits into
Open
Cache per-item color schemes in ListState to avoid list jank#27patrickunterwegs wants to merge 2 commits into
patrickunterwegs wants to merge 2 commits into
Conversation
getColorSchemeForSeedColor re-read theme preferences and regenerated a full dynamicColorScheme palette on every ListItem/TaskListItem, on every recomposition - expensive work repeated per row in a lazy list. Add rememberColorSchemeResolver(), which reads preferences once and memoizes the generated ColorScheme per distinct seed color, rebuilding only when the resolved theme inputs actually change. Wire it into the three list screens (Notes, Tasks, Journals); ListItem/TaskListItem gain an optional colorScheme parameter (default null, preserving existing behavior for every other caller, including previews and DetailsScreen's subtask list).
Replaces the rememberColorSchemeResolver()-based approach with a simpler design: ListState now holds a precomputed colorSchemes map, rebuilt in ListViewModel whenever the entry list or resolved theme inputs change, via the new recomputeColorSchemes() (kept separate from recompute(), which doesn't depend on theme). System dark mode can't be observed outside Compose, so ListScreenRoot - the one shared root for all three list variants - bridges it in via a single LaunchedEffect dispatching OnSystemDarkThemeChanged; the other theme prefs (palette style, AMOLED) are read directly from UserAppPreferencesStore's existing flows, same pattern already used for observeColors()/observeCategories(). ListItem/TaskListItem/the three list screens now do a plain colorSchemes[color] map lookup instead of calling a remembered resolver function. Color.kt reverts to its original, single-purpose form.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Superseded the original approach in this PR (a
rememberColorSchemeResolver()Compose helper threaded through 3 screens) with a simpler design that keeps the cache inListStateinstead:ListStategains acolorSchemes: Map<Color, ColorScheme>field, plus the resolved theme inputs it's derived from (themeOption,themePaletteStyle,themeAmoled,isSystemDark).ListState.recomputeColorSchemes()rebuilds that map from the distinct seed colors currently inicalEntries— kept deliberately separate fromrecompute()(filtering/sorting/grouping), since theme changes don't need to redo those, and vice versa.ListViewModelcallsrecomputeColorSchemes()whenevericalEntrieschanges, and independently observesUserAppPreferencesStore's theme flows (palette style, AMOLED, theme option) the same way it already observes colors/categories — no new DI needed there.@ComposableisSystemInDarkTheme().ListScreenRoot— the single shared root for all three list variants (Notes/Tasks/Journals) — bridges it in with oneLaunchedEffectdispatching a newOnSystemDarkThemeChangedaction.ListItem/TaskListItemand the three list screens now do a plainstate.colorSchemes[color] ?: MaterialTheme.colorSchememap lookup instead of calling a remembered resolver function.Color.ktreverts to its original, single-purpose form —rememberColorSchemeResolver()and its supporting helper are removed entirely.No background/async precomputation —
dynamicColorSchemeis a plain, cheap, pure function over a small number of distinct colors, so rebuilding the map synchronously inside the existing state-update flow is enough.Test plan
colorSchemesupdates correctlyisSystemInDarkTheme()bridge works