Skip to content

Commit

Permalink
Update UITableView to track changes precisely
Browse files Browse the repository at this point in the history
Previously we called reloadData() whenever anything changed
in the underlying model.

With this change we fire precise events to the UI when inserts
and removes happen in the source LazyList. This attempts to
coalesce changes to itemsBefore() and itemsAfter() with
adjacent changes and the beginning and end of the items list.
To implement this the changes are buffered into an intermediate
model before they are applied.

When a cell changes from being a placeholder to a loaded
item, or the opposite, this does a cell content change
without firing an event through the UITableView. To
implement this we must track which cells are currently
displaying placeholders. This PR includes a new datastructure,
SparseList, to implement this tracking.

This PR also changes the number of placeholders that
guest code offers to host code. I found experimentally
that 20 placeholders was not enough for UITableView.

This PR changes LazyList from UICollectionView to
UITableView. This change was potentially unnecessary,
though UITableView has fewer features that we don't
need.
  • Loading branch information
squarejesse committed Sep 29, 2023
1 parent f7cdc2c commit aad3385
Show file tree
Hide file tree
Showing 11 changed files with 1,522 additions and 141 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,14 @@ internal fun LazyList(
val itemsBefore = remember(state.firstVisibleItemIndex) { (state.firstVisibleItemIndex - OffscreenItemsBufferCount / 2).coerceAtLeast(0) }
val itemsAfter = remember(lastVisibleItemIndex, itemProvider.itemCount) { (itemProvider.itemCount - (lastVisibleItemIndex + OffscreenItemsBufferCount / 2).coerceAtMost(itemProvider.itemCount)).coerceAtLeast(0) }
val scrollItemIndex = remember(state.scrollToItemTriggeredId) { ScrollItemIndex(state.scrollToItemTriggeredId, state.firstVisibleItemIndex) }
var placeholderPoolSize by remember { mutableStateOf(20) }
var placeholderPoolSize by remember { mutableStateOf(30) }
LazyList(
isVertical,
itemsBefore = itemsBefore,
itemsAfter = itemsAfter,
onViewportChanged = { localFirstVisibleItemIndex, localLastVisibleItemIndex ->
val visibleItemCount = localLastVisibleItemIndex - localFirstVisibleItemIndex
val proposedPlaceholderPoolSize = visibleItemCount + visibleItemCount / 2
val proposedPlaceholderPoolSize = visibleItemCount * 2
// We only ever want to increase the pool size.
if (placeholderPoolSize < proposedPlaceholderPoolSize) {
placeholderPoolSize = proposedPlaceholderPoolSize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import app.cash.redwood.layout.api.CrossAxisAlignment
import app.cash.redwood.layout.widget.RedwoodLayoutTestingWidgetFactory
import app.cash.redwood.lazylayout.api.ScrollItemIndex
import app.cash.redwood.lazylayout.widget.LazyListValue
import app.cash.redwood.lazylayout.widget.ListUpdateCallback
import app.cash.redwood.lazylayout.widget.RedwoodLazyLayoutTestingWidgetFactory
import app.cash.redwood.lazylayout.widget.RedwoodLazyLayoutWidgetFactory
import app.cash.redwood.lazylayout.widget.WindowedLazyList
Expand Down

This file was deleted.

Loading

0 comments on commit aad3385

Please sign in to comment.