`DynamicList` is designed to support very large da...
# doodle
n
DynamicList
is designed to support very large datasets, just like
List
. the only difference is that
DynamicList
keeps an eye on its underlying model for changes and updates when there are any. This shouldn't affect scroll performance or having a model with gobs of data in it though. that's because all the
List
controls only render the contents within their display rect. this means they will only create Views for data that the user should be able to see. this makes them perfect for
ScrollPanel
since they will use windowing (and recycle the Views used for their items) as the user scrolls. embedding Lists is a great use for
ScrollPanel
.
a
Trying to load 1200 views in a ScrollPanel lagged alot. I think we will just go with DynamicList
n
yeah. use one if the Lists for this.
a
Regarding this, is there a way to observe the scroll position within a
ScrollPanel
? There's a scroll variable but it's not observable
n
hmm. there isn't an event for when it changes (maybe something i should add). but you can indirectly observe it by observing
boundsChanged
events for it's
content
. the
x
,
y
position of its content will change as scroll happens. can you share why you need this event? are you trying to manually decide what to load based on the scroll offset? if you're using a
List
or
DynamicList
, you can have model that has all the data you want. so you could populate it with the entire dataset if that data isn't some paginated set that comes from your backend for example. you would then use an
ItemVisualizer
that converts this raw data into a
View
on demand (and reuses/updates any
View
given to it). this visualizer would be called by the list whenever it needs to create/update a View. so the number of views in your scene will be a function of how many are visible in the list. putting this list in a ScrollPanel ensures that only a small fraction of the 1200 will be visible, and therefore you never have all of them active at once. now, this assumes your data is known all at once. if you need to stream your data as the list scrolls, you can take a look at the PhotoStream tutorial and how it uses a simple list model backed by Unsplashed that fetches more an more images as it scrolls. this is done w/o knowing anything about a ScrollPanel. instead, that model loads more images when an image is requested outside the range it currently has in memory. this has the same effect though, since the list will ask for items at indexes as it scrolls them into view. let me know if that helps, or if you really do need the scroll offset for a different reason.
a
Yea. We needed the scroll offset be able to calculate the last visible item. But I'll look into the implementation of the PhotoStream. Looks like it can help.
Hey Nick, so basic list behavior require an item height else it uses a default height. So let's say I have multiple views in the same list with different heights how can I achieve that??
I feel the list should use each item's height, but what do you think??
@Nick
n
hey @ayodele. you can have items in a
List
with different heights.
List
uses an ItemPositioner to manage the layout of its items. the positioner needs to be able to say which item is at a given
Point
within the
List
, and what bounds an item at an index has. the
ListBehavior
returned by basicListBehavior uses VerticalListPositioner, which assumes all items have the same height. but you could use your own that supports items of different heights; you'd just return appropriate values for these method calls. that said,
List
is inherently lazy loading. so it won't have an actual
View
when it needs to know what item to display at an arbitrary index. this is b/c the
List
might have to display items for a viewport at an arbitrary point (i.e. when it is within a
ScrollPanel
that jumps forward by a lot). so it first needs to gather the range of indexes to display from the positioner, create the newly visible views, then ask the positioner to specify their bounds. this means your positioner will need to be able to decide which
View
is at a
Point
without knowing what specific item will be visualized (since it won't necessarily exist yet). so your positioner would likely have some internal state to represent the list of item heights. this approach does not perform well for large lists if you want the views in the
List
to decide their heights. that's b/c you'd need to create all the n-1 views to know the position of the nth view. you would be able to cache values of course, but it still means jumping around in the list would be O(N) instead of O(1) if you wanted to ensure perfect scrolling.
a
@Nick regarding this discussion, we have a usecase whereby we have items and headers. More like a sectioned list. How do you suggest we achieve that?
n
@ayodele is the data you plan to store in the sectioned list small or known ahead of time? if so, it might be simpler to roll a custom
View
that you configure directly. here's some a basic example of one with a list of items that can all have their own heights and some custom spacing:
Copy code
val list = view {
    items.forEach {
        children += ... // add item or header and specify height
    }

    layout = simpleLayout { container ->
        var y = 0.0
        
        container.children.forEach {
            it.bounds = Rectangle(.., y = y, ...)
            y += it.height + spacing
        }

        // expand the view's height to fit its children
        height = children.lastOrNull().bounds.bottom ?: 0.0
    }
}
if the date set is large and you want to lazy load the Views, then the built-in
List
and its variants can help. but it will require you to do some work-arounds. that's b/c
List
doesn't support decorative/supplemental Views, which would help w/ the headers. so you'll have to have represent each header in the data model itself, use a
List<View>
with
ViewVisualizer
and simply include your headers in the list, or create a custom
ItemVisualizer
that will output headers at the correct index in the list. then--assuming its a requirement--providing different sizes for items would require what i mentioned above.
@ayodele, did you get a solution to this?