我想了解删除附加了事件侦听器的项目时的最佳做法。
例如:
我有一个包含许多子项的滚动视图。我想用不同的项目列表刷新scrollview的内容。
scrollview中包含的每个项目都附加了一个或多个eventlisteners。
我应该在删除项目之前删除事件侦听器吗? 要么 删除项目是否会自动清除所有附加的事件侦听器?
我试图通过让不再存在的UI对象具有活动侦听器来确保我不会影响性能或内存消耗。
答案 0 :(得分:2)
您应该阅读this。
JavaScript解释器扫描内存,查找没有引用的对象。然后销毁它们以释放它们正在消耗的内存。
如果从内存中删除了一个对象,它的事件侦听器也会消失。您不需要再次调用removeEventListener()。
因此,在您的情况下,删除子视图并确保没有其他引用就足够了。
答案 1 :(得分:1)
好问题。记忆是珍贵的" (在移动设备上使用最好的Gollum口音),创建泄漏绝对可以成为崩溃,低星评级和不满意用户的途径。关于添加/删除视图和关闭窗口时如何处理垃圾收集存在一些误解。关闭窗口会清除子视图,使用.remove()
方法实际上会从内存中删除视图等。
在这个特定的用例中,由于没有代码示例,我必须推测您如何创建子视图以及如何处理和设置事件监听器,但一般来说这应该适用于大多数的东西。
对于您的观点,我们假设您已在Alloy视图文件中定义了ScrollView(id =' scrollView'),并且您创建子视图时执行以下操作:
var subViews = [];
function _doSomething(){
alert('Something!');
}
for(i=0;i<10;i++){
var view = Ti.UI.createView({
backgroundColor:"#ececec",
height:50,
width: Ti.UI.FILL});
view.addEventListener('click', _doSomething);
subViews.push(view);
$.scrollView.add(view);
}
在上面的示例中,我们正在做一些事情:
1)我们创建一个数组来保存我们所有的子视图,所以如果我们需要引用一个特定的视图(ahem,用于垃圾收集),我们可以
2)我们正在声明我们的事件函数,而不是使用事件监听器内联创建它,所以我们可以在需要时清理它
现在 - 在任何用例中我们都准备好管理这个特定视图的记忆。
现在假设您决定删除该特定ScrollView的所有视图,并使用以下内容:
$.scrollView.removeAllChildren();
然后继续添加新观点。您的子视图刚刚消失了吗?那些事件听众呢?
答案 - 他们仍然在闲逛。它易于检查,只需抛出
console.log(subViews.length);
在您用于添加视图的代码的末尾(如上例所示),您将看到类似的内容。
[INFO] 10
[INFO] 20
[INFO] 30
[INFO] 40
[INFO] 50
[INFO] 60
[INFO] 70
因此,有了这些信息,您现在应该知道如何在准备好清除它们时清理子视图。以下是一个示例:
function cleanUpSubViews(){
while(subViews.length) {
var v = subViews.pop();
v.removeEventListener('click', _doSomething);
v = null;
};
}
一般情况下,清理子视图应该清除事件监听器,但是为了确保我建议在上面的代码中添加一行来确保处理它。
您可以在此查看一个有效的示例: https://gist.github.com/grantges/884ae6b2fd8570a89109
请务必查看Managing Memory上的文档以及我们的Best Practice Guides,以获取更多信息和清晰度。