As the Compose documents suggest, To make a composable stateless, We use state hoisting by replacing the state variable with two parameters: value and onValueChananged.
Something like this:
MyText(text: String, onTextChanged: (String) -> Unit
However, in some cases, the composable function gets a value without state hoisting, for example when we are interested in reading ScrollableState or LazyListState, we pass a remembered state to the composable function:
val lazyListState = rememberLazyListState()
LazyRow(state = lazyListState) {...}
With the given code above, let's assume that lazyListState is indirectly used in MyItem composable:
items(items = myItems,
key = { item -> item.id }) { item ->
val someDerivedState by remember {
derivedStateOf {
someComputationsWithLazyListState(lazyListState)
}
}
MyItem(item = item, deferredDerivedState = { someDerivedState })
}
Here is my question, How does compose keep lazyListState updated internally without passing it by something like oScrollstateChange?
Note that I'm not asking how to use LazyListState, The question is about how it works.
Well, It was easier than I thought, The short answer is
MutableState!Instead of
LazyListState, I start with a simpler example. Let's assume there is an interface namedPersonwith this contract:We want to update the age internally and let the Compose know, Here is how it is implemented:
Also, we can provide an instance of
PersonImplasPersonby a composable function, something likerememberLazyListState(ButLazyListStateis not an internal class):Note that
oneYearLateris added to simulate internal updates of the class. Every time that we invoke this function, Compose knows the state is changed and If any composable accepts it as a state, There will be a recomposition:So, every button click increases age by one and the Text will be updated.