Uploaded image for project: 'Titanium SDK/CLI'
  1. Titanium SDK/CLI
  2. TIMOB-26225

Android: TableView leaks memory when overwriting "data" property

    Details

    • Story Points:
      8
    • Sprint:
      2018 Sprint 15 SDK, 2018 Sprint 16 SDK

      Description

      Summary:
      Replacing a TableView's "data" array property causes a memory leak where the previous array of rows do not get garbage collected.

      Steps to reproduce:
      (Below requires an Android emulator and Chrome web browser to be installed.)

      1. Create a "classic" Titanium project with the below code.
      2. Go to the project directory at the command line.
      3. Enter: appc ti build -p android --debug-host /127.0.0.1:51388
      4. Wait for the app to launch. It'll "hang" on the splash screen.
      5. In the log, copy the the "chrome-devtools://devtools/bundled/inspector.html?..." URL.
      6. Open the Chrome browser and paste the copied URL.
      7. In Chrome, select the "Memory" tab.
      8. Select the "Allocation instrumentation on timeline" radio button.
      9. Click the "Start" button.
      10. Select the "Sources" tab.
      11. Click the "Resume script execution" toolbar button in top-right corner. Looks like: [>]
      12. Wait for the Titanium app to display a TableView.
      13. Click the "Reload" button in the bottom-right corner of the app.
      14. Click the Android back button.
      15. In Chrome, select the "Memory" tab.
      16. In Chrome, top-left corner, click the "Stop recording heap profile" toolbar button.
      17. Under the "Constructor" column, expand the "Label" tree.
      18. Note that 50 Labels are listed under it. These have not been garbage collected.

      function createTableData() {
      	var tableData = [];
      	var maxIndex = 50;
      //var maxIndex = Math.floor(Math.random() * 100) + 1;
      	for (var index = 1; index <= maxIndex; index++) {
      		var row = Ti.UI.createTableViewRow();
      		row.add(Ti.UI.createLabel({ text: "Row " + index.toString() }));
      		tableData.push(row);
      	}
      	return tableData;
      }
       
      var window = Ti.UI.createWindow({ exitOnClose: false });
      var container = Ti.UI.createView({
      	width: Ti.UI.FILL,
      	height: Ti.UI.FILL,
      });
      var tableView = Ti.UI.createTableView({
      	data: createTableData(),
      });
      container.add(tableView);
      var reloadButton = Ti.UI.createButton({
      	title: "Reload",
      	bottom: "10dp",
      	right: "10dp",
      });
      reloadButton.addEventListener("click", function(e) {
      	Ti.API.info("@@@ Reloading table data.");
      	tableView.data = createTableData();
      });
      container.add(reloadButton);
      window.add(container);
      window.open();
      

      Notes:

      • If a TableView is garbage collected, then its rows are correctly garbage collected as well. This is only an issue when overwriting the rows via the "data" property.
      • This is an issue for Alloy since its generated code will replace the TableView "data" array any time the model changes via a "fetch", "destroy", "change", "add", "remove", or "reset" event.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                gmathews Gary Mathews
                Reporter:
                jquick Joshua Quick
                Reviewer:
                Joshua Quick
              • Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:

                  Backbone Issue Sync

                  • Titanium SDK/CLI <> Titanium Mobile
                    Synced with:
                    TIMOB-6470
                    Sync status:
                    ERROR
                    Last received:
                    Last sent:

                    Git Source Code