Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-10445] Android: TableView "data" creation arg rows never get released even if complete row set is replaced later using setData

GitHub Issuen/a
TypeBug
PriorityMedium
StatusClosed
ResolutionCannot Reproduce
Resolution Date2015-11-05T00:36:11.000+0000
Affected Version/sRelease 2.1.1
Fix Version/sn/a
ComponentsAndroid
Labelscore, dev-investigate
ReporterBill Dawson
AssigneeHieu Pham
Created2012-08-14T14:50:21.000+0000
Updated2015-11-05T00:36:11.000+0000

Description

If you use set a table view's initial set of rows using the data property of a creation-time argument object (e.g. Ti.UI.createTableView({data: rows}); the rows that you set there never seemed to be released from memory if the tableview is in the current scope.

Test case

This test case requires that you know DDMS and MAT (Memory Analyzer Tool). No instructions are provided for that. 1. Use this app.js in a new app:

setInterval(function(){},1000);
var ROWS = 200;
var DATA_AT_CREATION = true;
Titanium.UI.setBackgroundColor('#333');

var win = Ti.UI.createWindow({
	exitOnClose: true,
	title:'Test',
	backgroundColor:'#333',
	orientationModes: [Ti.UI.PORTRAIT]
});
win.add(Ti.UI.createLabel({
	left: "8dp", right: "8dp", top: "8dp", height: "48dp",
	text: DATA_AT_CREATION ? "Initial data set at creation time" :
		"Initial data set via setData after creation"
}));

var tv, btnBuild, btnTeardown;
var iter = 0;

var buildup = function() {
	iter++;
	var rows=[], i;

	for (i = 0; i < ROWS; i++) {
		rows.push(
			Ti.UI.createTableViewRow({
				title: "Iter " + iter + "; Row " + (i + 1),
				height: "48dp"
		}));
	}
	return rows;
};

if (DATA_AT_CREATION) {
	win.add(tv = Ti.UI.createTableView({
		top: "64dp", bottom: "64dp", data: buildup()
	}));
} else {
	win.add(tv = Ti.UI.createTableView({
		top: "64dp", bottom: "64dp"
	}));
	tv.setData(buildup());
}

win.add(btnBuild = Ti.UI.createButton({
	bottom: "8dp", height: "48dp", left: "16dp", width: "112dp",
	title: "Build up"
}));

win.add(btnTeardown = Ti.UI.createButton({
	bottom: "8dp", height: "48dp", left: "144dp", width: "112dp",
	title: "Tear down"
}));

btnBuild.addEventListener("click", function() {
	tv.setData(buildup());
});

btnTeardown.addEventListener("click", function() {
	tv.setData([Ti.UI.createTableViewRow({title: "empty"})]);
});

win.open();
2. Run the app and click "Build up" several times (5 times is fine). Each time you click that you replace the rows in the table view with 200 new rows. 3. Click "Tear down" 4. Let the device/emulator idle for 40 seconds (this gives extra opportunities for the V8 GC to run.) 5. In DDMS, find the running app, turn on heap updates for it, and cause GCs until the heap size stabilizes. 6. Export the HPROF for MAT. 7. In MAT, get a dominator tree and sort it by package. 8. Find the ti.* packages, and drilldown to ti.modules.titanium.ui. 9. Look at the number of TableViewProxy objects: there will probably be about 211, even though there is only 1 row in the table after you click that "Tear down" button. When testing a fix, this number should be down at 11 or so.

Compare to using setData

1. Change the constant DATA_AT_CREATION to false up near the top of app.js. 2. Follow steps 2-8 from above. This time when you check the number of TableViewProxy objects, it should be 11 or so.

Attachments

FileDateSize
Eclipse_Memory_Analyzer.png2015-11-05T00:29:01.000+0000187066

Comments

  1. Bill Dawson 2012-08-14

    Note that this could be a general thing about proxy creation args; I just happened to notice it with TableView.
  2. Ingo Muschenetz 2014-04-14

    Needs investigation to see if it still exists.
  3. Wilson Luu 2015-11-05

    Closing ticket as cannot reproduce. Verified that the TableViewProxy object count is consistently below 11 in the following scenarios (using the above steps): * Setting the DATA_AT_CREATION to true * Setting the DATA_AT_CREATION to false * Build up five times and more * Tested against Android device and Genymotion running 4.4.X * See !Eclipse_Memory_Analyzer.png|thumbnail! *Tested on:* Appcelerator Studio, build: 4.4.0.201511040454 Appc CLI NPM: 4.2.1 Appc CLI Core: 5.1.0-42 Arrow: 1.3.18 SDK: 5.1.0.v20151104110027 Node: v4.2.1 OS: El Capitan (10.11.1) Devices: Samsung Galaxy S5 (4.4.2), Genymotion Emulator (4.4.4) *Notes for getting HPROF from DDMS:* * You will need to enable your Titanium app for Android debugging; add this in tiapp.xml:
       <android xmlns:android="http://schemas.android.com/apk/res/android">
               <manifest>
                   <application android:debuggable="true"/>
               </manifest>
           </android>
       
    * Here is the link to the stand-alone memory analyzer: https://eclipse.org/mat/downloads.php. * Once you have obtained the .hprof file from DDMS, you will need to convert it with Android tool's hprof-conv .

JSON Source