Stylianos Gakis
08/21/2021, 12:12 PMSideEffect {}
triggers more than 10 times a second forever without anything changing on the screen.
More details in thread đ§”Stylianos Gakis
08/21/2021, 12:12 PMSideEffect { Timber.d("Recompose Triggered") }
as it says that it runs after every recomposition therefore I hope this is the correct approach.
When I donât add any of the code I will post below this, the endless recomposition does not happen so I am fairly certain this is what brings the problem.
I want to have a function that has the signature of
fun LazyListState.isLastItemVisibleAsState(): State<Boolean>
For the implementation, I have tried numerous things so far, with all of them triggering the infinite recomposition or having other problems.
To start with, I tried this
val lastItemIndex = remember { mutableStateOf(this.layoutInfo.visibleItemsInfo.lastOrNull()?.index) }
return remember(this) {
derivedStateOf {
lastItemIndex.value == this.layoutInfo.totalItemsCount - 1
}
}
But this one obviously doesnât work as lastItemIndex simply captures the value on first composition and then never updates
So I thought Iâd provide as the key to remember the index itself thinking that when it changes, the remember should re-calculate the value it holds like this:
val lastItemIndex = remember(layoutInfo.visibleItemsInfo.lastOrNull()?.index) {
mutableStateOf(layoutInfo.visibleItemsInfo.lastOrNull()?.index)
}
return derivedStateOf {
lastItemIndex.value == this.layoutInfo.totalItemsCount - 1
}
But this triggers recomposition forever. I assumed that what would happen here is the layoutInfo.visibleItemsInfo.lastOrNull()?.index
returns the same index, therefore the mutable state does not change, therefore there is no need for a recomposition.
I thought maybe I should wrap the derivedStateOf
with a remember
call but this didnât help either.
I at that point noticed that layoutInfo.visibleItemsInfo returns a different set of items on every recomposition, and itâs just a list not coming as State<T>
, so maybe this has something to do with all of this?
I donât know how to approach this problem, which mechanisms should be used (remember
derivedStateOf
etc.) and how to understand why what I am doing is not what Compose expects me to do and does all these unnecessary recompositions.
So my question would be, how would you implement this function with the signature that I propose at the beginning, and if you do have a nicely working solution, why does that work while my approaches have all been unsuccessful?
Also, am I just tripping at this point, am I doing something incredibly and fundamentally wrong? I do not know.Dominaezzz
08/21/2021, 12:16 PMfun LazyListState.isLastItemVisibleAsState(): State<Boolean>
is not a good function imo. I think you definitely just want,
fun LazyListState.isLastItemVisibleAsState(): Boolean
.Dominaezzz
08/21/2021, 12:17 PMremember
or derivedStateOf
for "performance" until you measure/benchmark.Stylianos Gakis
08/21/2021, 12:18 PMLazyListState
change, so I thought it would make sense to return it as a State
to denote that the result of this will be forcing recomposition (when it legitimately changes, not all the time). Is this a wrong approach, how would I denote that with a function that seemingly just returns a boolean as a one shot operation?Dominaezzz
08/21/2021, 12:20 PMisLastItemVisibleAsState
in a composable function, it'll subscribe to what ever state it touches and update itself accordingly.Dominaezzz
08/21/2021, 12:20 PMLazyListState
is already a State<...>
so all you need to do is read from it.Stylianos Gakis
08/21/2021, 12:28 PMval isLastItemVisible = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index == lazyListState.layoutInfo.totalItemsCount - 1
on my composable, it recmposes infinitely. Shouldnât that âjust workâ if it is a State?Dominaezzz
08/21/2021, 12:29 PMrememberUpdatableState()
then.Dominaezzz
08/21/2021, 12:31 PMval isLastItemVisible by rememberUpdatableState(lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index == lazyListState.layoutInfo.totalItemsCount - 1)
Stylianos Gakis
08/21/2021, 12:31 PMvisibleItemsInfo
I think is the one that returns a different list each time and that maybe is what is messing this all up. It feels like everything I t*hink* I know about compose goes out of the window with this problem.Dominaezzz
08/21/2021, 12:31 PMStylianos Gakis
08/21/2021, 12:34 PMisLastItemVisible
itâs there greyed out as not-used.
And just to clarify, by rememberUpdatableState()
I assume you mean rememberUpdatedState()
right?Dominaezzz
08/21/2021, 12:36 PMDominaezzz
08/21/2021, 12:36 PMDominaezzz
08/21/2021, 12:37 PMval isLastItemVisible by remember { derivedStateOf { lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index == lazyListState.layoutInfo.totalItemsCount - 1 } }
Stylianos Gakis
08/21/2021, 12:47 PMderivedStateOf
and are simply putting everything in there for it to handle for us automatically.
Ah sometimes itâs somewhat frustrating, like what do I need to read to be able to understand all of this? Just trial and error until it âclicksâ?Dominaezzz
08/21/2021, 12:51 PMStylianos Gakis
08/21/2021, 12:52 PMDominaezzz
08/21/2021, 12:52 PMState
in them đ .Dominaezzz
08/21/2021, 12:52 PMStylianos Gakis
08/21/2021, 12:53 PMStylianos Gakis
08/24/2021, 11:42 PMÂ is not a good function imo. I think you definitely just want,fun LazyListState.isLastItemVisibleAsState(): State<Boolean>
I just had another discussion around this with some different context about another function with the same signature difference and I feel like you would be interested in reading it especially after we had this discussion here before @Dominaezzz It seems like not only is this function signature not necessarily ânot a good functionâ but it also come with some potential benefits as discussed here https://kotlinlang.slack.com/archives/CJLTWPH7S/p1629839151061400 . And after I changed by implementation it also limits the recompositions only to the scope that actually use this value. Just thought of sharing it with you because I am sure you would be interested in it đfun LazyListState.isLastItemVisibleAsState(): Boolean
Dominaezzz
08/25/2021, 7:55 AMStylianos Gakis
08/25/2021, 7:58 AMDominaezzz
08/25/2021, 8:06 AMStylianos Gakis
08/25/2021, 8:08 AM