确认最佳实践:删除EventListeners

时间:2016-02-12 13:57:47

标签: memory-management appcelerator event-listener appcelerator-titanium

我想了解删除附加了事件侦听器的项目时的最佳做法。

例如:

我有一个包含许多子项的滚动视图。我想用不同的项目列表刷新scrollview的内容。

scrollview中包含的每个项目都附加了一个或多个eventlisteners。

我应该在删除项目之前删除事件侦听器吗? 要么 删除项目是否会自动清除所有附加的事件侦听器?

我试图通过让不再存在的UI对象具有活动侦听器来确保我不会影响性能或内存消耗。

2 个答案:

答案 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,以获取更多信息和清晰度。