1616
1717package androidx.compose.foundation.lazy.layout
1818
19+ import androidx.collection.mutableIntIntMapOf
1920import androidx.collection.mutableIntObjectMapOf
2021import androidx.collection.mutableIntSetOf
2122import androidx.compose.foundation.ExperimentalFoundationApi
@@ -42,7 +43,7 @@ internal abstract class CacheWindowLogic(
4243 * Cache for items sizes in the current window. Holds sizes for both visible and non-visible
4344 * items
4445 */
45- private val windowCache = mutableIntObjectMapOf< CachedItem > ()
46+ private val windowCache = mutableIntIntMapOf ()
4647 private var previousPassDelta = 0f
4748 private var previousPassItemCount = UnsetItemCount
4849 private var hasUpdatedVisibleItemsOnce = false
@@ -119,7 +120,15 @@ internal abstract class CacheWindowLogic(
119120 * changed.
120121 */
121122 if (previousPassItemCount != UnsetItemCount && previousPassItemCount != totalItemsCount) {
122- onDatasetChangedSize()
123+ debugLog { " Total Items Changed" }
124+ shouldRefillWindow = true
125+ prefetchWindowStartLine = prefetchWindowStartLine.coerceAtLeast(0 )
126+ val lastLineIndex = getLastLineIndex()
127+ if (lastLineIndex != InvalidIndex ) {
128+ prefetchWindowEndLine = prefetchWindowEndLine.coerceAtMost(lastLineIndex)
129+ }
130+ /* * Free up the space so the fill will happen and not re-use old data. */
131+ removeOutOfBoundsItems(prefetchWindowEndLine, itemsCount - 1 )
123132 }
124133
125134 itemsCount = totalItemsCount
@@ -128,8 +137,8 @@ internal abstract class CacheWindowLogic(
128137 // by [cancelOutOfBounds]. If any items changed sizes we re-trigger the window filling
129138 // update.
130139 if (hasVisibleItems) {
131- forEachVisibleItem { index, key, mainAxisSize ->
132- if (index != InvalidIndex ) cacheVisibleItemsInfo(index, key, mainAxisSize)
140+ forEachVisibleItem { index, mainAxisSize ->
141+ if (index != InvalidIndex ) cacheVisibleItemsInfo(index, mainAxisSize)
133142 }
134143 if (shouldRefillWindow) {
135144 // refill window in accordance with last pass delta
@@ -225,25 +234,6 @@ internal abstract class CacheWindowLogic(
225234 }
226235 }
227236
228- private fun CacheWindowScope.onDatasetChangedSize () {
229- debugLog { " Total Items Changed" }
230- shouldRefillWindow = true
231- prefetchWindowStartLine = prefetchWindowStartLine.coerceAtLeast(0 )
232- val lastLineIndex = getLastLineIndex()
233- if (lastLineIndex != InvalidIndex ) {
234- prefetchWindowEndLine = prefetchWindowEndLine.coerceAtMost(lastLineIndex)
235- }
236-
237- /* *
238- * Resets the window state. We will refill the window on the direction of the last scroll.
239- */
240- if (previousPassDelta <= 0f ) {
241- removeOutOfBoundsItems(lastVisibleLineIndex, itemsCount - 1 )
242- } else {
243- removeOutOfBoundsItems(0 , firstVisibleLineIndex)
244- }
245- }
246-
247237 fun resetStrategy () {
248238 prefetchWindowStartLine = Int .MAX_VALUE
249239 prefetchWindowEndLine = Int .MIN_VALUE
@@ -293,7 +283,7 @@ internal abstract class CacheWindowLogic(
293283 // If we get the same delta in the next frame, would we cover the extra space needed
294284 // to actually need this item? If so, mark it as urgent
295285 val isUrgent: Boolean =
296- if (prefetchWindowEndLine + 1 == visibleWindowEnd + 1 && scrollDelta != 0.0f ) {
286+ if (prefetchWindowEndLine + 1 == visibleWindowEnd + 1 ) {
297287 scrollDelta.absoluteValue >= mainAxisExtraSpaceEnd
298288 } else {
299289 false
@@ -325,9 +315,7 @@ internal abstract class CacheWindowLogic(
325315 // If we get the same delta in the next frame, would we cover the extra space needed
326316 // to actually need this item? If so, mark it as urgent
327317 val isUrgent: Boolean =
328- if (
329- prefetchWindowStartLine - 1 == visibleWindowStart - 1 && scrollDelta != 0.0f
330- ) {
318+ if (prefetchWindowStartLine - 1 == visibleWindowStart - 1 ) {
331319 scrollDelta.absoluteValue >= mainAxisExtraSpaceStart
332320 } else {
333321 false
@@ -370,7 +358,7 @@ internal abstract class CacheWindowLogic(
370358 while (prefetchWindowStartExtraSpace > 0 && prefetchWindowStartLine > 0 ) {
371359 val item =
372360 if (windowCache.containsKey(prefetchWindowStartLine - 1 )) {
373- windowCache[prefetchWindowStartLine - 1 ]!! .mainAxisSize
361+ windowCache[prefetchWindowStartLine - 1 ]
374362 } else {
375363 break
376364 }
@@ -385,7 +373,7 @@ internal abstract class CacheWindowLogic(
385373 while (prefetchWindowEndExtraSpace > 0 && prefetchWindowEndLine < itemsCount - 1 ) {
386374 val item =
387375 if (windowCache.containsKey(prefetchWindowEndLine + 1 )) {
388- windowCache[prefetchWindowEndLine + 1 ]!! .mainAxisSize
376+ windowCache[prefetchWindowEndLine + 1 ]
389377 } else {
390378 break
391379 }
@@ -398,16 +386,13 @@ internal abstract class CacheWindowLogic(
398386
399387 private fun CacheWindowScope.getItemSizeOrPrefetch (index : Int , isUrgent : Boolean ): Int {
400388 return if (windowCache.containsKey(index)) {
401- debugLog { " Item $index is Cached!" }
402- windowCache[index]!! .mainAxisSize
389+ windowCache[index]
403390 } else if (prefetchWindowHandles.containsKey(index)) {
404391 // item is scheduled but didn't finish yet
405- debugLog { " Item=$index is already scheduled. isUrgent=$isUrgent " }
406392 if (isUrgent) prefetchWindowHandles[index]?.fastForEach { it.markAsUrgent() }
407393 InvalidItemSize
408394 } else {
409395 // item is not scheduled
410- debugLog { " Scheduling Prefetching for Item=$index . isUrgent=$isUrgent " }
411396 prefetchWindowHandles[index] =
412397 schedulePrefetch(index) { prefetchedIndex, size ->
413398 onItemPrefetched(prefetchedIndex, size)
@@ -419,7 +404,7 @@ internal abstract class CacheWindowLogic(
419404
420405 /* * Grows the window with measured items and prefetched items. */
421406 private fun cachePrefetchedItem (index : Int , size : Int ) {
422- windowCache[index] = updateOrCreateCachedItem(index, size, CachedItem . NoKey )
407+ windowCache[index] = size
423408 if (index > prefetchWindowEndLine) {
424409 prefetchWindowEndLine = index
425410 prefetchWindowEndExtraSpace - = size
@@ -429,34 +414,18 @@ internal abstract class CacheWindowLogic(
429414 }
430415 }
431416
432- private fun updateOrCreateCachedItem (index : Int , size : Int , key : Any ): CachedItem {
433- val cachedItem = windowCache[index]
434- return if (cachedItem != null ) {
435- cachedItem.mainAxisSize = size
436- cachedItem.key = key
437- cachedItem
438- } else {
439- CachedItem (CachedItem .NoKey , size)
440- }
441- }
442-
443417 /* *
444418 * When caching visible items we need to check if the existing item changed sizes. If so, we
445419 * will set [shouldRefillWindow] which will trigger a complete window filling and cancel any out
446- * of bounds requests. The same is valid if items are replaced (have the same size by key
447- * changed).
420+ * of bounds requests.
448421 */
449- private fun cacheVisibleItemsInfo (index : Int , key : Any , size : Int ) {
450- debugLog { " cacheVisibleItemsInfo item=$index size=$size key=$key " }
451- if (windowCache.containsKey(index)) {
452- val cachedSize = windowCache[index]!! .mainAxisSize
453- val cachedKey = windowCache[index]!! .key
454- if (cachedSize != size || cachedKey != key) {
455- shouldRefillWindow = true
456- }
422+ private fun cacheVisibleItemsInfo (index : Int , size : Int ) {
423+ debugLog { " cacheVisibleItemsInfo item=$index size=$size " }
424+ if (windowCache.containsKey(index) && windowCache[index] != size) {
425+ shouldRefillWindow = true
457426 }
458427
459- windowCache[index] = updateOrCreateCachedItem(index, size, key)
428+ windowCache[index] = size
460429 // We're caching a visible item, remove its handle since we won't need it anymore.
461430 prefetchWindowStartLine = minOf(prefetchWindowStartLine, index)
462431 prefetchWindowEndLine = maxOf(prefetchWindowEndLine, index)
@@ -470,8 +439,6 @@ internal abstract class CacheWindowLogic(
470439
471440 windowCache.forEachKey { if (it in startLine.. endLine) indicesToRemove.add(it) }
472441
473- debugLog { " Indices to remove=$indicesToRemove " }
474-
475442 indicesToRemove.forEach {
476443 prefetchWindowHandles.remove(it)?.fastForEach { it.cancel() }
477444 windowCache.remove(it)
@@ -534,19 +501,15 @@ internal interface CacheWindowScope {
534501
535502 fun getVisibleItemLine (indexInVisibleLines : Int ): Int
536503
537- fun getVisibleLineKey (indexInVisibleLines : Int ): Any
538-
539504 fun getLastIndexInLine (lineIndex : Int ): Int
540505
541506 fun getLastLineIndex (): Int
542507}
543508
544509internal inline fun CacheWindowScope.forEachVisibleItem (
545- action : (itemIndex: Int , itemKey: Any , mainAxisSize: Int ) -> Unit
510+ action : (itemIndex: Int , mainAxisSize: Int ) -> Unit
546511) {
547- repeat(visibleLineCount) {
548- action(getVisibleItemLine(it), getVisibleLineKey(it), getVisibleItemSize(it))
549- }
512+ repeat(visibleLineCount) { action(getVisibleItemLine(it), getVisibleItemSize(it)) }
550513}
551514
552515private const val InvalidItemSize = - 1
@@ -560,7 +523,3 @@ private inline fun debugLog(generateMsg: () -> String) {
560523 println (" CacheWindowLogic: ${generateMsg()} " )
561524 }
562525}
563-
564- internal class CachedItem (var key : Any , var mainAxisSize : Int ) {
565- companion object NoKey
566- }
0 commit comments