[TIMOB-17147] IOS: ScrollableView: cacheSize property does not work when the view has a child view component
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | Low |
Status | Closed |
Resolution | Invalid |
Resolution Date | 2017-05-02T22:07:40.000+0000 |
Affected Version/s | Release 3.2.3 |
Fix Version/s | n/a |
Components | iOS |
Labels | community |
Reporter | Shuo Liang |
Assignee | Eric Merriman |
Created | 2014-06-12T07:20:02.000+0000 |
Updated | 2017-05-02T22:07:40.000+0000 |
Description
The "cacheSize" property of the ScrollableView allows the developer to define how many "pages" are to be pre-rendered when the ScrollableView is loaded. As the user scrolls, additional pages are pre-redendered as needed. This is useful for complex scrollable views with many items as it increases performance and reduces memory use.
Problem:
If the pages (views) contains child views, the cacheSize property does not work and all pages are pre-rendered at once. When loading hundreds of complex pages, this results on the ScrollableView becoming very slow as it is not taking advantage of the cache logic.
Test case:
The code below shows this problem. You can set the TEST_CASE variable between 1 and 4 to test the four different cases.
The first two cases load only a single view control (a view, and an imageview). These two cases work, and as can be seen from the console log, only 3 pages are pre-rendered initially, and as you scroll additional pages are pre-rendered as needed. Remote images are loaded as needed as well.
The last two cases load views with children (3 = a view with a child imageview, and 4 = a view with a child view). As can be seen from the console, these two cases fail, as cacheSize is ignored and the ScrollableView pre-renders all 100 pages at once.
app.js
// window
var win = Ti.UI.createWindow({
title: 'TEST',
backgroundColor: '#ffffff'
});
// returns array of remote images (from kitchensink)
function getPhotos() {
var data = [];
var baseUrl = 'http://placehold.it/';
var imageUrl;
for (i=30;i<40;i++){
for (j=30;j<40;j++){
imageUrl = baseUrl+i+'x'+j;
data.push(imageUrl);
}
}
return data;
}
// load event for remote image
function img_load(e) {
Ti.API.info('Loaded remote image ' + e.source.id + ': ' +e.source.image);
}
// postlayout event for view
function view_postlayout(e) {
Ti.API.info('Post-layout ' + e.source.id);
}
// scrollable view with set cache size set to 3
var pager = Ti.UI.createScrollableView({
cacheSize: 3
});
// assemble and open
win.add(pager);
win.open();
//
// TEST CASE SELECTOR (1, 2, 3 or 4)
//
var TEST_CASE = 1;
// simulate 2s delayed xhr call to bind scrollable view with data
setTimeout(function() {
var photos = getPhotos(),
pages = [];
// TEST CASE BRANCH
if (TEST_CASE == 1)
{
// CACHESIZE WORKS HERE: ONLY 3 VIEWS ARE LOADED
// load empty container views
for (var i = 0; i < photos.length; i++)
{
// container view
var cont = Ti.UI.createView({ id: i, width: 300, height: 300, backgroundColor: 'red' });
cont.addEventListener('postlayout', view_postlayout);
// add container views to list
pages.push(cont);
}
}
else if (TEST_CASE == 2)
{
// CACHESIZE WORKS HERE: ONLY 3 IMAGES ARE LOADED
// load imageviews directly (no container view)
for (var i = 0; i < photos.length; i++)
{
// image
var img = Ti.UI.createImageView({ id: i, image: photos[i], width: 200, height: 200 });
img.addEventListener('load', img_load);
// add imageview to list
pages.push(img);
}
}
else if (TEST_CASE == 3)
{
// CACHESIZE DOES NOT WORK HERE: ALL CONTAINERS AND CHILD REMOTE IMAGES ARE LOADED AT ONCE
// load imageviews inside a container view
for (var i = 0; i < photos.length; i++)
{
// image view
var img = Ti.UI.createImageView({ id: i, image: photos[i], width: 200, height: 200 });
img.addEventListener('load', img_load);
// container view
var cont = Ti.UI.createView({ id: 'container '+i, width: 300, height: 300, backgroundColor: 'blue' });
cont.addEventListener('postlayout', view_postlayout);
cont.add(img);
// add container to list
pages.push(cont);
}
}
else if (TEST_CASE == 4)
{
// CACHESIZE DOES NOT WORK HERE: ALL CONTAINERS AND CHILD VIEWS ARE LOADED AT ONCE
// load view inside a container view
for (var i = 0; i < photos.length; i++)
{
// child view
var child = Ti.UI.createView({ id: 'child '+i, width: 200, height: 200, backgroundColor: 'red' });
child.addEventListener('postlayout', view_postlayout);
// container view
var cont = Ti.UI.createView({ id: 'container '+i, width: 300, height: 300, backgroundColor: 'blue' });
cont.addEventListener('postlayout', view_postlayout);
cont.add(child);
// add container to list
pages.push(cont);
}
}
// bind pages to scrollable view
pager.applyProperties({
views: pages,
currentPage: 0
});
}, 2000);
Expected result:
cacheSize should work regardless if the pages are single controls or composite controls.
will this be taken on for a fix on 3.3.1? it's a big issue for us that cacheSize is broken since we make extensive use of ScrollableViews on our app to browse content and images. thank you!
I'm still seeing this problem with the v3.4.0GA daily build, as well as v3.3.0. I've narrowed down the test and found the problem seems to be related to when the scrollableview pages are bound: If they are bound before the scrollableview is added to the window, then cacheSize works. If they are bound after the scrollableview has been added to the window, then cacheSize does not work. (This scenario is very common, since data can be pulled from a remote api and then bound to an already rendered scrollableview) Here's another test case to show this. Comment and uncomment the two lines below the two test conditions to see the difference. Test 1 binds the pages (views) before the scrollableview is added to the window and cacheSize works as expected as shown by the console log. Test 2 binds the pages after the scrollableview has been added to the window, and cacheSize is ignored. All thirteen pages are rendered with remote images downloaded when the pages are bound as can be seen by the log. The setTimeout() is there to make sure the pages are bound after the window .add() method, and to simulate pulling data from a remote api to build the pages. I hope this can be fixed in 3.4.0. This is the number one issue that will keep us from publishing, since we make use of scrollable views with _hundreds_ of pages that load remote data. Since cacheSize fails, all remote data is loaded at once, slowing the app, eating up lots of memory and making the app unstable (crashing).
Hey guys, Is this issue already fixed? Thanks.
Any news about this?
same here, this bugs is breaking our application
Resolving ticket as Invalid as there is now a new version of Kitchen Sink available and we no longer support the version which relates to this ticket.