Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-9491] iOS: Table view scrolling lags/freezes when dynamically adding rows

GitHub Issuen/a
TypeBug
PriorityMedium
StatusClosed
ResolutionInvalid
Resolution Date2012-06-19T18:02:49.000+0000
Affected Version/sRelease 2.0.2, Release 2.0.1
Fix Version/sn/a
ComponentsiOS
LabelsSupportTeam, api, support
ReporterBetty Tran
AssigneeVishal Duggal
Created2012-06-11T17:35:41.000+0000
Updated2017-05-31T22:37:09.000+0000

Description

Problem

When adding rows to a table view dynamically each time the table has scrolled close to the end, the scrolling becomes jerky and the app is unresponsive. The table rows contain images and labels.

Test Case

var buildRow = function() {
	var rowView = Titanium.UI.createTableViewRow({
		className : 'lolcat',
		layout : "vertical",
		height : 350,
		backgroundColor : 'pink'
	});

	var imgAvatar = Titanium.UI.createImageView({
		image : 'http://placekitten.com/g/50/50',
		height : 50,
		width : 50,
		top : 5,
		left : 5
	});

	rowView.add(imgAvatar);

	var avaLabel = Ti.UI.createLabel({
		text : "Super Cat",
		font : {
			fontSize : 12,
			fontWeight : 'bold'
		},
		top : 5,
		left : 65
	});

	rowView.add(avaLabel);

	var imgThingy = Titanium.UI.createImageView({
		image : 'http://placekitten.com/g/300/200',
		height : 200,
		width : 300
	});

	rowView.add(imgThingy);

	var postTitle = Ti.UI.createLabel({
		text : "Cat saves the day",
		font : {
			fontSize : 18,
			fontWeight : 'bold'
		}
	});

	rowView.add(postTitle);

	var postText = Ti.UI.createLabel({
		text : "At 12, a helicopter crashed and all passengers were saved by this cat",
		font : {
			fontSize : 10,
		}
	});

	rowView.add(postText);
	
	return rowView;
}

var buildTable = function() {
	var data = [];
	var table = Ti.UI.createTableView({
		top : 0,
		right : 0,
		bottom : 0,
		left : 0
	});

	for (var i = 0; i < 5; i++) {
		data.push(buildRow());
	}

	table.setData(data);

	table.addEventListener('scroll', function(e) {
		if (e.contentOffset.y + e.size.height + 100 > e.contentSize.height) {
			table.appendRow(buildRow());
			table.appendRow(buildRow());
			table.appendRow(buildRow());
			table.appendRow(buildRow());
			table.appendRow(buildRow());
		}
	});

	return table;
}

var win = Ti.UI.createWindow({
	backgroundColor : '#fff'
});

var table = buildTable();

win.add(table);

win.open(); 

Comments

  1. Vishal Duggal 2012-06-19

    Trying to update a tableView while it is scrolling will result in lags/freezes and generally jerky behavior. That is because you have two competing processes running alternately on the main thread. Would advise that tableView update not be done on the scroll event but instead on a explicit user action. You can use either the headerPullView (See KS for an example) or the footerView properties of the table. Attaching example for footerView
       var buildRow = function() {
           var rowView = Titanium.UI.createTableViewRow({
               className : 'lolcat',
               layout : "vertical",
               height : 350,
               backgroundColor : 'pink'
           });
           
           var w1 = Math.round(Math.random()*100+50);
           var w2 = Math.round(Math.random()*100+300);
        	
           var imgAvatar = Titanium.UI.createImageView({
               //image : 'http://placekitten.com/g/50/50',
               image : 'http://placekitten.com/g/'+w1+'/'+w1,
               height : 50,
               width : 50,
               top : 5,
               left : 5
           });
        
           rowView.add(imgAvatar);
        
           var avaLabel = Ti.UI.createLabel({
               text : "Super Cat",
               font : {
                   fontSize : 12,
                   fontWeight : 'bold'
               },
               top : 5,
               left : 65
           });
        
           rowView.add(avaLabel);
        
           var imgThingy = Titanium.UI.createImageView({
               //image : 'http://placekitten.com/g/300/200',
               image : 'http://placekitten.com/g/'+w2+'/'+w2,
               height : 200,
               width : 300
           });
        
           rowView.add(imgThingy);
        
           var postTitle = Ti.UI.createLabel({
               text : "Cat saves the day",
               font : {
                   fontSize : 18,
                   fontWeight : 'bold'
               }
           });
        
           rowView.add(postTitle);
        
           var postText = Ti.UI.createLabel({
               text : "At 12, a helicopter crashed and all passengers were saved by this cat",
               font : {
                   fontSize : 10,
               }
           });
        
           rowView.add(postText);
            
           return rowView;
       }
        
       var buildTable = function() {
           var data = [];
           var table = Ti.UI.createTableView({
               top : 0,
               right : 0,
               bottom : 0,
               left : 0
           });
        
           for (var i = 0; i < 5; i++) {
               data.push(buildRow());
           }
        
           table.setData(data);
           
           var footerView = Ti.UI.createView({
           	width:Ti.UI.FILL,
           	height:Ti.UI.SIZE
           });
           var button = Ti.UI.createButton({
           	width:Ti.UI.FILL,
           	height:Ti.UI.SIZE,
           	title:'Load More Data'
           })
           footerView.add(button);
           
           button.addEventListener('click',function(e){
                   table.appendRow(buildRow());
                   table.appendRow(buildRow());
                   table.appendRow(buildRow());
                   table.appendRow(buildRow());
                   table.appendRow(buildRow());
           })
           
           table.footerView = footerView;
        
           return table;
       }
        
       var win = Ti.UI.createWindow({
           backgroundColor : '#fff'
       });
        
       var table = buildTable();
        
       win.add(table);
        
       win.open(); 
       
  2. Fokke Zandbergen 2013-08-02

    I suggest this issue to be re-opened. Automatically loading more rows while scrolling is a very common concept, that should be supported in Titanium.
  3. Sameeh Harfoush 2013-12-27

  4. Alan Leard 2013-12-27

    ListView handles this very well on both platforms. Please review the guide documentation here and compare your results: http://docs.appcelerator.com/titanium/latest/#!/guide/ListViews
  5. Sameeh Harfoush 2013-12-27

    well i am still figuring out how to create the template and subtemplates to fit my data-model. the thing is that every single feed contains views that are created by calling other classes (modular) that create the necessary view UI. for example, the main container view contains four types of UI: first UI for the user, second one is for a business, third is for voting...etc. the data model is a bit complicated to map on a listview template, so listview is not feasible solution at this point...i still don't understand why a screen can render on Android and not on iPhone? is is a native UI limitation for iOS?
  6. Lee Morris 2017-05-31

    Closing ticket as invalid.

JSON Source