-
Notifications
You must be signed in to change notification settings - Fork 13.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: virtual scroll #1157
WIP: virtual scroll #1157
Conversation
related #65 |
Awesome! I'll give it a go and let you know. |
Hey, Just tried it out. I probably have a fairly complex case, which I guess is good for testing purposes, but it didn't really work yet unfortunately. My list datasource is populated after the controller loads since it's loaded via the This mean that initially I got an error because the datasource was undefined, so I set it to an empty array when the controller is instantiated and that error went away, but when the data was loaded the list didn't update. Also, with an empty array the list showed up one item with no content in it. Another thing with my list is that I'm using bindonce for performance reasons (once loaded my items don't really change). I removed this to make sure that it wasn't interacting with the virtual scroll and confirmed it had the same issues. Let me know if you need a plunkr to reproduce or want me to do more testing :) Thanks |
Oh and the other thing - at the moment I'm passing a few filters into the data source so that sorting and categorisation can be applied on the fly without having to update the datasource in the controller. Will the current implementation work for that? I also removed that for my first round of testing to make sure it wasn't that. |
All those use cases sound like they should work - it's getting a lot more polished now, should be done or nearly done today. |
OK cool - I'll wait to hear back from you when I should test again :) |
Thanks for the help so far! |
@robdmoore would you be able to try it out again? It's a lot closer now to where we want it. Syntax: <something scroll-collection-repeat="item in items" scroll-item-size="52">
</something> The size is a pixel amount. Note: keep your dom elements simple for this. As you scroll down, it compiles new items and inserts them into the DOM. I've only been able to get it to perform great when my items are relatively simple. |
OK, serious updates happenin'. It's about as ready as it's gonna be, I think. @robdmoore and everyone, it's ready to test.
Warning: keep your dom as simple as possible. Even the example in list-fit.html janks a tiny bit on older android phones because it has to compile three new dom elements every time the user scrolls down. Please lemme know any problems you find. Now to just finish the unit tests, add errors for user misbehavior, document it, add anymore optimizations we can, and merge! |
@ajoslin, awesome work. I noticed a few things I think we should tweak or think about before release: First of all, it's fricking fast as all hell on my iPhone 5. Crazy! People are going to love this.
Of course, if we ship this today as-is, it will be a big step forward, so maybe these can wait? Thoughts? |
I will try and implement the grid before releasing, incase it requires a breaking api change. |
Also, one bug: the items are transformed wrong for one frame when scrolling up, causing a tiny flicker (you can see it if you scroll slowly). Some bad math on the rendering I think. |
@ajoslin what about the API change would have to break? Instead of item-size being a single value, it could take a comma separated (space-friendly) size: `scroll-item-size="100, 200". Or is it a different part of the API that would change? |
* @returns {string} hash string such that the same input will have the same hash string. | ||
* The resulting string key is in 'type:hashKey' format. | ||
*/ | ||
function hashKey(obj) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Guys. I'm excited to see this in action! I had a thought that I'll share in case you think it makes sense. Please take it or leave it as you see fit.
It might be nice to add simple support for ng-repeat's "track by" syntax. If present, you could then skip the hashKey fn call getting a tiny performance gain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, will add it. The point of of the track by
syntax is that we can hash some id to cache an item's value instead of caching the whole object itself - it lets us know better whether we need to re-compile an item, or if we can use a cached one.
Wow. That gif is AMAZING. One of the funniest I've seen in a PR thread. impressed. Will check this out with my list and get back to you. |
OK - I've given this a go with my list. The performance of the page is immeasurably better. Scrolling is smoother and in particular moving on and off the page is super fast! I did notice a few issues on my list:
Great work so far - this is really exciting! |
Thanks @robdmoore ! Pushed a fix. A small request, could you number your bugs? Makes it easier for us to discuss them as numbers. I edited your comment.
|
Also fixed slight item flicker while scrolling up (was due to some bad math). |
Fixed the items sometimes looking uncompiled. |
Awesome! I'll produce a plunkr tomorrow to try and reproduce what I'm seeing and try out the latest changes :) |
Now to get the grid syntax working, then unit test time! I'm doing unit tests last here because the inner-workings are in such a state of flux. |
Grid works now. If you specify two sizes, it will use the second to fill in the secondary direction. In this case, the secondary direction is horizontal because our scroller is vertical. Using separate repeat-elements in your grid It's slightly slower than the old solution, since it has to compile {{itemsOnRow}} seperate elements each time you scroll. But it's not actually a very noticeable difference at all. As usual, it's important to remember simpler DOM is always better for your infinite repeater. Try out the pull-to-refresh as well. |
Hey. Great job. Do not think about it? P.S. Sorry for my bad English. |
Hi @rotorgames. Yes, it is slow if you are using complicated DOM. Can you post your markup, and your css rules? Your idea is interesting: taking over the DOM/css's positioning system and position things ourselves. With your idea for a solution, we would still be inserting and removing elements from the DOM, but not repositioning. It is an interesting idea. I will think about it. It definitely has downsides, not using the CSS/DOM's positioning. Thanks for the feedback. And please post your HTML/CSS. |
@ajoslin, tomorrow see your code. I'll try to remake a "-webkit-transform: translate". |
@rotorgames sounds great, look forward to seeing it. |
So after a lot of testing on a basic implementation, it is definitely a noticeable boost in performance on older Androids or with complicated DOM. The downside is it forces people to explicitly set the width of their items in their CSS, due to the items becoming position:absolute. Also, we aren't really using the DOM for positioning anymore - how bad is this actually? I'm not sure yet. I'll see what you come up with tomorrow @rotorgames and consider implementing it! Thanks for the tip! |
FYI - I've run out of time for this today unfortunately sorry! Will definitely try and look tomorrow. |
@udfalkso: You can use a getter to make your first item different: <div collection-repeat="item in repeatedItems"
collection-item-height="getHeight(item)">
<div ng-switch="item.isBig">
<div ng-switch-when="true">I'm a big offset item</div>
<div ng-switch-default>{{item}}</div>
</div>
</div> //Every time items is changed, update repeatedItems to match
$scope.$watchCollection('items', function() {
$scope.repeatedItems = [ {isBig: true} ].concat($scope.items);
});
$scope.getItemHeight = function(item) {
return item.isBig ? 200 : 50;
}; |
@robdmoore working on all this stuff today. |
Awesome! thanks mate :) |
Also wow - the latest version with the scope digesting improvement is SO MUCH SMOOTHER! Even on iPad! exciting :-) |
Finally finished all unit tests! I should have done that a lot earlier, but we kind of rushed the release of this. @robdmoore can you try scroll position on back in the latest nightly? |
..Also, ionItem compile error fixed in latest! |
Thanks @ajoslin - It wasn't pretty, but I managed to use this approach to get it the result I was looking for. I hope you'll consider incorporating a smoother solution to this in the future. Thanks again for the great work, this feature is huge. |
Just not sure of a better solution yet. I will think about it. |
Hi @ajoslin, I've pulled in the latest nightly and tried it out:
I've also noticed the following (happy to add a separate issue for any of these you want and if they don't make sense / you can't replicate let me know and I'll try and create a plunkr):
|
|
Hmm, for 3. What do you mean by 'performance issue'? Lag in compiling, or scrolling, or loading the next page? |
Cool will do re: reproducable issues. re: 3 as in changing from the page to the next page. |
re: 1 I've figured out it's because we are using |
Yes, the ion-header-bar directive adds the has-* classes. If you don't use the directive, you'll have to add them on your own. Also, I saw your other issue - will look into it. Thanks for so much detailed feedback, Robert! |
No worries - thanks for being so responsive to the things I notice! It makes all the difference :) Good to know re: ion-header-bar. I assume the same is true for ion-footer-bar? |
Hmm I'm struggling to try and replicate my weird problem where all the items show up at the top in a basic plunkr. Will have to try again tomorrow. |
OK, ruled out a few things:
Will keep trying... |
Is it possible your collection-item-height function is ever returning 0? |
No I hardcode it to 84. I think it might be to do with the data somehow. If I comment out the bit that sets the data with a static array of items then it seems to work. There isn't much fancy in the data - just some nested arrays (I just checked if that was the cause and it didn't seem to be)). |
This could be a red herring, but it seems that if I have a nested array of hashes in my items then it might cause it to sometimes happen. I can't replicate in my plunkr though, hmm how frustrating! OK I'm calling it a night, it's really late haha. Will try again tomorrow. |
Haha, thanks for looking. Sounds definitely very weird. Goodnight. |
Hey, I'm still struggling to replicate this outside of my app. If you were debugging the problem I am describing (it's rendering every item in the list rather than say 5 and they all appear at position 0,0) what part of the ionic code would you put breakpoints in? I can't publish the code because it's a commercial application - is there any possibility of hooking up a Skype call so you can see it via screen share though? |
Hi rob, I wouldn't really know where to start until I saw it.. I guess I would find Just search your ionic.bundle.js for 'render = func'. I could definitely do a Skype call though. My time zone is gmt-7. Email me
|
Rob's problems fixed, closing. 💃 |
🍰 |
@robdmoore if you wanna test, here it is so far
Test in /test/html/list-fit.html
TODO: