Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-17479] iOS: Memory leak when ListView template contains an event listener that update the listview

GitHub Issuen/a
TypeBug
PriorityNone
StatusResolved
ResolutionCannot Reproduce
Resolution Date2017-06-11T17:47:04.000+0000
Affected Version/sRelease 3.3.0
Fix Version/sn/a
ComponentsiOS
LabelsTCSupport, ios
ReporterKaga
AssigneeUnknown
Created2014-06-25T22:41:13.000+0000
Updated2018-02-28T20:04:09.000+0000

Description

Problem Description

The TiUIListViewProxy is never released and the memory usage keeps increasing with Titanium SDK 3.3.0 and 3.2.X.GA. It’s a valid bug.

Testing Environment:

Mac OS X 10.9 Ti CLI 3.3.0 Titanium SDK: 3.3.0.RC and 3.2.X.GA iOS 7.1

Test Code


// This is a single context application with multiple windows in a stack
(function() {

var createTableWin = function(){
	var tableWin = Ti.UI.createWindow({backgroundColor: 'white'});

	var myTemplate = {
	    childTemplates: [
	        {
	            type: 'Ti.UI.Label',
	            bindId: 'titleLabel',
	            properties: {
	                width: '50%',
	                height: '100%',
	                left: '0dp'
	            }
	        },
	        {
	            type: 'Ti.UI.TextField',
	            bindId: 'textfield',
	            properties: {
	            	width: '49.5%',
					right: '0dp',
					borderStyle: Ti.UI.INPUT_BORDERSTYLE_ROUNDED
	            },
	            events: {
					focus: function(event) {

					},
					blur: function(event) {
						var sections = [];
						var fruitSection = Ti.UI.createListSection({ headerTitle: 'Fruits / Frutas'});
						var fruitDataSet = [
						    { titleLabel: {text: 'Apple'}},
						    { titleLabel: {text: 'Banana'}},
						    { titleLabel: {text: 'One more item'}}
						];
						fruitSection.setItems(fruitDataSet);
						sections.push(fruitSection);
						listView.setSections(sections);
					},
					change: function(event) {

					}
				}
	        }
	    ]
	};

	var listView = Ti.UI.createListView({
	    templates: { 'template': myTemplate },
	    defaultItemTemplate: 'template'
	});
	var sections = [];



	var fruitSection = Ti.UI.createListSection({ headerTitle: 'Fruits / Frutas'});
	var fruitDataSet = [
	    { titleLabel: {text: 'Apple'}},
	    { titleLabel: {text: 'Banana'}}
	];
	fruitSection.setItems(fruitDataSet);
	sections.push(fruitSection);

	listView.setSections(sections);
	tableWin.add(listView);

	return tableWin;
};

//empty root win
var rootWin = Ti.UI.createWindow({backgroundColor: 'white'});
var leftButton = Ti.UI.createButton({
	title: 'open'
});
leftButton.addEventListener('click', function(){
	iosNav.openWindow(createTableWin());
});
rootWin.setLeftNavButton(leftButton);



var iosNav = Ti.UI.iOS.createNavigationWindow({
	window: rootWin
});
iosNav.open();


})();

Steps To Test

- Create a new project - Update app.js file with sample code - Run on iPad simulator 7.1 - Test allocation summary for running 10 times - Memory usage keeps increasing. Screenshot: https://www.dropbox.com/s/jn0xsh5rltbrbao/Screen%20Shot.jpg

Expected Result

It’s not working as expected.

Attachments

FileDateSize
app.js2014-06-25T22:41:13.000+00002081

Comments

  1. Mauro Parra-Miranda 2014-08-10

    Thanks for your report. The Platform team will set the priority on this issue.
  2. François Mériaux 2014-08-11

    I met the same issue. It only appears when the templates include event listeners. As a workaround, I removed the listeners from the templates and I set a listener to the 'itemclick' event on the ListView. Then I recognize which element had been clicked by playing with bindID and itemIndex of the source. Something like:
       function manageClick(e) {
       	Ti.API.debug('in profile detail, click spotted on listview');
       	if (e.itemIndex === startActivitiesIndex) {
       		if (e.bindId) {
       			if ((e.bindId === 'bleftChevronBox') || (e.bindId === 'bfaLeftChevron')) {
       				loadPreviousActivities();
       			} else if ((e.bindId === 'brightChevronBox') || (e.bindId === 'bfaRightChevron')) {
       				loadNextActivities();
       			} else if ((e.bindId === 'bleftTitleBox') || (e.bindId === 'bfaClock')) {
       				sortByTimestamp(function() {
       				});
       			} else if ((e.bindId === 'brightTitleBox') || (e.bindId === 'bfaComment')) {
       				sortByCommentTimestamp(function() {
       				});
       			}
       		}
       	}
       }
       $.listview.addEventListener('itemclick', manageClick);
       
    This way, the memory leak does not occur.
  3. Ed 2014-08-11

    I'm seeing this memory leak as well on my app. I also try to use the listview's 'itemclick' event as a workaround whenever possible (as suggested by François above), but it does not work for non-click events, like 'change', 'selected', etc. Hoping we can get a fix on the next 3.3.1, as my app uses several templated listviews. Thanks.
  4. Jonas Funk Johannessen 2015-03-24

    Me too. ItemTemplate with event will not clear the proxies. Hoping this PR will help fix this issue. https://github.com/appcelerator/alloy/pull/671
  5. Hans Knöchel 2017-06-11

    I am unable to reproduce this leak in Titanium SDK 6.0+, testing with Instruments and the Allocations instrument.

JSON Source