Whenever I try to move the pager state from the composable to my viewmodels the pager state stops remembering and the currently selected page is reset to zero on screen rotation changes. Here, I'm pasting a full working example where there are two lines commented:
- Option 1 uses a
PagerState
object stored in a viewmodel, which survives screen rotation and thus should keep the current page. - Option 2 uses a
rememberPagerState()
inside the composableWrapper
.
So when I run the example using option 1 (viewmodel), reach the last page and rotate the screen, or enter window mode, change dark mode, or anything that generates a configuration change, the page is lost and I return to page 0. However, when I use the option 2 (rememberPagerState) the page is kept. Ironically, the print()
that is placed before the HorizontalPager
shows that when running the viewmodel option the object address is the same, yet in option 2 it changes every time.
What is going on? Why does HorizontalPager
reset the page when I'm passing PagerState
from the ViewModel
or a global?
class TestViewModel: ViewModel() {
@OptIn(ExperimentalFoundationApi::class)
val pagerState = PagerState()
init {
println("ddd Initializing TestViewModel!")
}
}
class MainActivity : ComponentActivity() {
private val vm: TestViewModel by viewModels()
@OptIn(ExperimentalFoundationApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
PagerStateTheme {
Wrapper(vm.pagerState)
}
}
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun Wrapper(pagerState: PagerState) {
val otherState = rememberPagerState()
//Test(pagerState = pagerState) // option 1
//Test(pagerState = otherState) // option 2
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun Test(pagerState: PagerState) {
println("ddd pager state object is $pagerState")
HorizontalPager(
pageCount = 4,
state = pagerState,
modifier = Modifier.fillMaxWidth(),
pageSpacing = 8.dp,
pageSize = PageSize.Fixed(300.dp),
contentPadding = PaddingValues(
start = 20.dp,
end = 20.dp,
top = 60.dp
),
) { pageIndex ->
Box(modifier = Modifier.fillMaxSize()) {
Text("Hello page $pageIndex")
}
}
}
This example was built from the current Android Studio IDE template, after adding the following gradle dependencies:
implementation platform('androidx.compose:compose-bom:2023.05.01')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
implementation 'androidx.compose.material3:material3'
implementation "androidx.compose.runtime:runtime-livedata"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1"