Skip to content

Home screen reloads content on return from Song Presenter; scroll position is not preserved #49

Description

@SiroDevs

Two related regressions occur when navigating back to the Home screen from the Song Presenter, Dafts, History and Settings:

  1. Content reloads from scratch. The song list visibly re-fetches and shows the shimmer skeleton loader briefly before re-rendering, even though nothing has changed.
  2. Scroll position resets to the top. Even when the reload does not trigger, the search tab's LazyColumn scrolls back to item 0 rather than returning to the position the user was at before tapping a song.

Steps to reproduce (reload)

  1. Open the app. Wait for songs to load.
  2. Tap any song to enter the Presenter.
  3. Press back.
  4. Observe: the shimmer loader briefly appears and songs reload.

Steps to reproduce (scroll reset)

  1. Open the app and scroll down past ~10 songs in the search tab.
  2. Tap a song to open the Presenter.
  3. Press back.
  4. Observe: the list is back at the top instead of where you left off.

Expected behaviour

  • Returning to the Home screen should show the search tab exactly as it was left — same scroll position, same query, same results — with no reload.
  • The dataFetched guard should be sufficient to prevent a re-fetch, but the LazyListState scroll position should also survive the navigation round-trip.

Root cause (technical)

There are two separate causes:

1. fetchData() is called again on recomposition via LaunchedEffect(Unit)

HomeScreen.kt calls viewModel.fetchData() inside a LaunchedEffect(Unit). The HomeViewModel has a dataFetched boolean guard to prevent double-loading, which should work because the ViewModel survives the back stack. However, if the HomeViewModel is being re-created on return (e.g. due to how hiltViewModel() scopes work with the nav graph), the guard resets to false and a full reload fires. The uiState transitions back through UiState.Loading, which HomeScreen maps to HomeSkeletonScreen(), causing the visible shimmer flash.

2. LazyListState is created with rememberLazyListState() and is not survived across navigation

In HomeSearch.kt, the list state is declared as:

val listState = rememberLazyListState()

rememberLazyListState() is tied to the composition lifetime of HomeSearch. When the user navigates to the Presenter, the HomeSearch composable leaves the composition (the NavHost replaces it). On return, HomeSearch recomposes from scratch and rememberLazyListState() returns a new instance at position 0, losing the previous scroll position.

Metadata

Metadata

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions