最佳实践的确认:删除事件监听器

Confirmation of Best Practice: Removing EventListeners

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

例如:

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

滚动视图中包含的每一项都附加了一个或多个事件监听器。

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

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

好问题。移动设备上的内存 "precious"(用最好的 Gollum 口音完成),造成泄漏肯定会导致崩溃、低星级和不满意的用户。关于在添加/删除视图和关闭时如何处理垃圾回收存在一些误解 windows。关闭 windows 清理子视图,使用 .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) 我们创建了一个数组来保存我们所有的子视图,所以如果我们需要引用一个特定的视图(咳咳,为了垃圾回收)我们可以

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, along with our Best Practice Guides 的文档,以获取更多信息并清楚地了解这一点。

你应该阅读 this

the JavaScript interpreter sweeps through memory looking for objects to which no references remain. Those are then destroyed to release the memory they were consuming.

如果一个对象从内存中移除,它的事件侦听器也会消失。您无需再次调用 removeEventListener()。

因此,对于您的情况,删除子视图并确保没有其他引用就足够了。