How to stop for loop after it had filled the array once and use the array

You must Login before you can answer or comment on any questions.

Hi,

I got a for loop creating buttons and will be stored in an array. The buttons are placed in the first view of the scrollableView. When I slide only 1 screen to the right and back everything is fine. Because scrollabelView will prerender the next view and hold the previous slide in memory.

But when I go to view 2, 3 or higher, and I want to go back to the first view (with the buttons) it want to refill the array with the for loop. After all, the array will be the same because the for loop is the same. But it leads to huge lag in the application. You won't be able to slide for some seconds. It wants to reload all the images. It's the connection time of searching the images that takes ages. All 42 buttonimages (of the 21 buttos) have a total of 200kb.

So how can I make it only make/load once and not every time when I get back to the first view (v0)?

app.js

var win = Ti.UI.createWindow({
    backgroundColor: '#eee'
});
 
var btnWidth = 130;
var btnHeight = btnWidth;
var screenWidth = btnWidth * (Math.floor(Ti.Platform.displayCaps.platformWidth / btnWidth));
 
/*Home view with buttons*/
var v0 = Ti.UI.createScrollView({backgroundColor:'#eee', width:'auto', height:'auto',});
 
var v0cont = Ti.UI.createView({
    backgroundColor: '#eee',
    layout: 'horizontal',
    width: screenWidth,
    height: 'auto',
    top: (btnWidth / 6)
});
 
v0.add(v0cont);
Titanium.Gesture.addEventListener('orientationchange', function(e){
    v0cont.setWidth(btnWidth * (Math.floor(Ti.Platform.displayCaps.platformWidth / btnWidth)));
});
/*end of home view*/
 
/*all views*/
var v1 = require('view/v1');
var v2 = require('view/v2');
var v3 = require('view/v3');
var v4 = require('view/v4');
var v5 = require('view/v5');
var v6 = require('view/v6');
var v7 = require('view/v7');
var v8 = require('view/v8');
var v9 = require('view/v9');
var v10 = require('view/v10');
var v11 = require('view/v11');
var v12 = require('view/v12');
var v13 = require('view/v13');
var v14 = require('view/v14');
var v15 = require('view/v15');
var v16 = require('view/v16');
var v17 = require('view/v17');
var v18 = require('view/v18');
var v19 = require('view/v19');
var v20 = require('view/v20');
var v21 = require('view/v21');
/*end of all views*/
 
 
/*scrollableView*/
var view = Ti.UI.createScrollableView({
    views:[v0,v1,v2,v3,v4,v5,v6,v7,v8,v9,v10,v11,v12,v13,v14,v15,v16,v17,v18,v19,v20,v21],
    showPagingControl:true,
    width: '100%',
    currentPage: 0,
    scrollType: 'horizontal'
});
/*end of scrollableView*/
 
 
/*Adding buttons*/
var data = [];
 
for(var x = 1;x<22;x++){
    var newBtn = Ti.UI.createButton({
        pagelink: x, 
        width:btnWidth, 
        height:btnHeight,
        backgroundImage: 'images/buttons/btn'+x+'.png',
        backgroundSelectedImage: 'images/buttons/btn'+x+'s.png',
    });
 
    newBtn.addEventListener("click",btnCallback);
    v0cont.add(newBtn);
    data.push(newBtn);
}
 
function btnCallback(e)
{
    view.currentPage = e.source.pagelink;
}
/*End buttons*/
 
win.add(view);
win.open();
v1.js: (at the moment v1 - v21 are the same, but will be different)
var screen = Ti.UI.createScrollView({
    backgroundColor:'#F16', 
    layout: 'horizontal', 
    width: Ti.Platform.displayCaps.platformWidth,
    height: Ti.Platform.displayCaps.platformHeight,
    scrollType: 'vertical'
});
 
var labelv1 = Ti.UI.createLabel({
    color: '#900',
    font: { fontSize:48 },
    shadowColor: '#aaa',
    shadowOffset: {x:5, y:5},
    text: 'Label text for v1',
    textAlign: Ti.UI.TEXT_ALIGNMENT_CENTER,
    top: 30,
    width: 'auto',
    height: 'auto'
});
 
screen.add(labelv1);
module.exports = screen;

— asked 9 months ago by Jesse R
3 Comments
  • Can I do something like

    if app is just opened, use forloop, else use data array? Or something with a timer?

    — commented 9 months ago by Jesse R

  • or an if else based on number of items in array?

    — commented 9 months ago by Jesse R

  • I try to use an if else, so if it comes back it would use the array but doesn't work..

    Does the scrollableView delete arrays of when you're +2 or -2 views?

    var data = [];
     
        if (data.lenght > 1) {
                v0cont.push(data)
            }
     
        else {
            for(var x = 1;x<maxbtn;x++){
                var newBtn = Ti.UI.createButton({
                    pagelink: x, 
                    width:btnWidth, 
                    height:btnHeight,
                    backgroundImage: 'images/buttons/btn'+x+'.png',
                    backgroundSelectedImage: 'images/buttons/btn'+x+'s.png',
                });
     
                newBtn.addEventListener("click", btnCallback);
                v0cont.add(newBtn);
                data.push(newBtn);
            }
        };
     
    function btnCallback(e)
    {
        view.currentPage = e.source.pagelink;
    }

    — commented 9 months ago by Jesse R

1 Answer

I'm not sure why your v0 is so laggy when you try to return to it. Are you saying that each individual button image is 400KB? Or the total is 400KB? Twenty buttons of about 20KB each doesn't sound too bad.

However, I don't think I would load 20 views full of UI elements into a scrollable view. Even if you are able to speed up v0, I think you're going to ultimately run into performance problems with that application design.

Maybe there's another way to structure your user interface so that you only load the views as the user needs them.

— answered 9 months ago by Jason Priebe
answer permalink
5 Comments
  • An image is 3.2 - 3.4 kb so say 140kb for all the 42 images. It's not the image size that is the problem but the connection to find the images in the resources. A single image of 4mb is faster loaded than 20 small images because of the speed of the connection.

    After the for loop is used, the buttons should be in the array. Once the array is filled with the for loop I want to use the array instead of using the for loop for a second, third or fourth time. There is no need to fill the array again because it will be the same.

    But I can't figure out how to use the array once it is filled..

    — commented 9 months ago by Jesse R

  • What confused me was this wording:

    But when I go to view 2, 3 or higher, and I want to go back to the first view (with the buttons) it want to refill the array with the for loop.

    The way you describe it, the data array is getting rebuilt when you scroll back to v0. But that's not the case (unless your actual code is very different from what you posted here). If you create v0 and add the buttons to it, then add v0 to the ScrollableView, when you scroll away from v0 and then back to v0, it shouldn't recreate v0 from scratch. The code in app.js that builds the array of buttons will only run one time.

    But you're obviously seeing some sort of lag, so it's possible that while the buttons are already created and they're already added to v0, the runtime engine / underlying UI elements may be reloading the image from the original URLs.

    In my experience, if you have an imageview in a scrollableview and you scroll away from that view and then back to it, the image is cached and appears immediately (even if it originally took a long time to load).

    But I don't know all the details of how that caching works. It's certainly possible that when you put 20 images in a single view of the scrollable view, and then have 20 other views, the underlying libraries may not keep your 20 images in cache.

    You could always pull down the images yourself and cache them explicitly. Kevin Hopkins has a very interesting cached ImageView class. Just make sure you convert it to CommonJS before you use it (shouldn't be too hard -- it's already very close). You could also convert this code into a cached Button class (although you can often do the same sort of things with ImageViews as Buttons).

    — commented 9 months ago by Jason Priebe

  • Thanks for the info. I'll take a look at it later today.

    It's still strange that it want to rebuild all the buttons. Also here is the console info

    As you can see: It want to get the backgroundImage 3 times and the button backgroundSelectedImage 1 time. It doesn't make any sense why it tries to get the backgroundImage 3 times.

    — commented 9 months ago by Jesse R

  • Show 2 more comments

Your Answer

Think you can help? Login to answer this question!