2013-03-05 173 views
3

我已阅读了很多网页,讨论如何控制基于Titanium的Android移动应用程序中的内存泄漏。钛内存管理

我的情况是,我正在构建一个应用程序,使用多级列表(实际上这些是tableViews),用户可以在其中浏览。它使用一个窗口,当用户选择一个列表项目时,会创建一个从右向左动画的新视图。我选择了这个选项,因为似乎不可能创建一个从右向左滑入所有平台的新窗口。

在每一个视图中,都会创建一个eventListener来检查哪个tableRow被点击,然后创建相应的子菜单并在屏幕中生成动画。

我注意到,每次点击视图后内存使用量稳步增长,但我似乎无法查明内存泄漏的存在位置。

目前我正在检查主窗口,以查看该窗口是否在视图外动画(然后,320px宽度的设备上的.left属性为320)。然后,我从窗口中删除此视图,并将代理设置为空,使用:

for (i = 0; i < win.children.length; i++) { 
    if ((win.children[i] != null) && (win.children[i].left == 320)) { 
     win.remove(win.children[i]); 
     win.children[i] = null; 
    } 
} 

尽管如此,它仍在建立内存使用情况。这可能是因为每一个新视图包含表和事件侦听器,使用包含功能:

var sub_table = Ti.UI.createTableView({top:'50dp',separatorColor: rowSeparatorColor}); 
sub_table.setData(data); 
sub_table.addEventListener('click', function(e) { 
    create(e.rowData.data); 
}); 
new_view.add(my_navbar); 
new_view.add(sub_table); 
return new_view; 

我必须单独清除它们或者是当视图被销毁他们摧毁?我必须手动清除它们,我该怎么做?

在更一般的说明中,我不知道如何确定内存使用的原因。有没有办法在特定时间获取内存中的所有对象和/或变量?有没有办法深入了解Dalvik工具包提供的内存使用情况?有没有获取所有全局变量或事件侦听器的方法?

+0

您可以使用dalvik工具包来分析由钛生成的Android项目,请检查它的构建文件夹。还可以尝试使用'removeEventListener' – 2013-03-05 17:37:14

回答

2

Titanium应用程序中最常见的内存泄漏与持有变量引用有关。如果你在上下文中有一个上下文,那么外部上下文的变量将保持到无效。如下所示。通过过滤TiUI并观看视图数量和视图代理数量增加(如果删除下面的所有“= null”行),可以在Apple的“工具”中轻松观察到这一点。

var win = Ti.UI.createWindow(); 
win.open(); 

setInterval(function() { 
    var view = Ti.UI.createView({ 
     backgroundColor: 'red', 
     width: 300, height: 300, 
     top: 100, left: 100 
    }); 
    win.add(view); 

    setTimeout(function() { 
     fadeAwayAndRemove(view, win); 
     view = null; 
    }, 1000); 
}, 2000); 

function fadeAwayAndRemove(view, container) { 
    var animation = { 
     opacity: 0, 
     duration: 300, 
     transform: Ti.UI.create2DMatrix().scale(0.9, 0.9) 
    }; 
    view.animate(animation, function() { 
     container.remove(view); 
     view = container = animation = null; 
    }); 
} 

还要注意的是,在上面的例子,如果我添加观点,即“观点”说我删除,我并不需要显式删除, 一次一个。确保你取消了所有对它们的引用。然后,当视图被删除并且无效时,GC可以清理它以及它的所有子项。

这种做法将开始成为你的第二天性。但是当你第一次开始考虑它的时候,在你的应用中重复离散操作是一个好主意(转到一个屏幕,回到前一个屏幕,转到同一屏幕,向后导航等等)来查找你失去最多记忆的地方。然后处理代码以消除排水。

它有时可能会很艰难和令人沮丧,但坚持下去,我知道你会弄明白的!

0

而且会这样的事情也工作?在这种情况下,我设置了侦听器,并将侦听器附加到表中。在表单被点击后,监听器被移除,并且使用create()方法创建一个新表。 它递归地工作(create()函数在点击表后调用它自己),这让我很怀疑。但它'应该'删除eventListener,从窗口中删除视图并将其代理设置为零?

function create(i) { 
    var listener = function(e) { 
     win.removeEventListener('click', listener); 
     win.remove(clickedview); 
     clickedview = null; 
     create(e.rowData.data); 
    } 
    var sub_table = Ti.UI.createTableView({top:'50dp',separatorColor: rowSeparatorColor}); 
    sub_table.setData(data); 
    sub_table.addEventListener('click', listener); 
    new_view = populateView(i); 
    new_view.add(sub_table); 
} 
+0

难以从示例中看出来。它可以。最好的方法是将它带到客观上告诉你它是否正常工作的东西 - Xcode Instruments。 (可能有一个Android版本会给你提供相同的信息 - 生活和垃圾收集的视图和代理的数量 - 但我不是最新的atm。) – 2013-03-07 04:34:03

1

我没有使用过Android内存管理器,只有Apple Instruments应用程序。

第一件事就是看看你的应用程序,而不是作为一个整体。我逐行检查了主窗口的代码,确保消除了我所知道的任何内存问题。我能够在我的主窗口上获得基线数量的对象,并将其用于与我的应用中的其他窗口进行比较。然后,我会在这些窗口之间切换并解决所有内存问题,希望每次都能看到我分配的对象数返回到我的基线。

例如,如果我打开我的主窗口,我希望分配2个按钮和2个标签。我转换到下一个窗口,它有2个按钮和2个标签,我希望看到这些对象的数量跳到4和4.然后我回到我的主窗口并关闭另一个窗口,我期望看到2额外的按钮和标签最终会被清理干净。这不是即时的,所以我刷新或看着确保它们消失。

请记住,你可以评论你的代码的巨大部分,看看它是不是罪魁祸首。例如,当我怀疑某段代码中有泄漏时,我将该代码注释掉,并查看对象实例数是否增加并按预期下降。

我发现,如果我关闭了一个窗口,所有分配的对象最终都会被清理干净,如果我让它们正确声明的话。我发现我的变量的1-2个例子缺少'var'关键字,所以我相信他们正在全局范围内声明,所以我清理了它。

我在Appcelerator的论坛贴出寻求帮助我,这里是我的帖子: http://developer.appcelerator.com/question/148246/profiling-and-cleaning-up-objects

这篇文章有几个建议,以及由Appcelerator的,讨论有关调试应用程序的视频的链接。

+0

尽管这个答案非常有用,但测试像那样在Android中似乎没有多大的帮助 - 操作系统只会在需要内存时释放对象。因此,您无法关闭窗口并期望内存立即被释放。 – LucasA 2015-04-27 21:11:05