4
  • 应用类型:手机
  • 钛 SDK:3.1.1.GA
  • 平台和版本:iOS 6.1
  • 设备:iOS模拟器
  • 主机操作系统:OSX 10.8.4
  • 钛工作室:3.1.1.201306112235

parent_controller.js:

_.each(category, function(inventory_item, index, list) {

    var row = Alloy.createController('inventory_list_row', {
        selectedBackgroundColor: '',
        data: inventory_item
    });

    row.destroy();
    row = null;

});

Ti.App.fireEvent('checkIn');

库存列表行.js:

Ti.App.addEventListener('checkIn', function(e) {
    console.info('Checking In: ' + args.data.title);
});

前言:上面的代码被淡化以证明一个观点。我知道它并没有真正做任何事情,但它确实有问题。

parent_controller.js 中的代码可以根据我的 Titanium Mobile iPad 应用程序中的用户交互执行多次。如果上面的代码只在一切正常后运行。每次上面的代码再次运行时,以前的控制器都会在内存中保留一些,并且仍在捕获事件。

例如,假设第一次执行代码时生成了 3 个inventory_list_row 控制器。在控制台中,我将看到 3 条“签入”消息按预期出现。但是,第二次运行时,我会在控制台中看到 6 条“签入”消息,依此类推。

为什么会这样,我能做些什么来防止这种情况发生?您可以看到我尝试使用 .destroy 并将 row 设置为 null 无济于事。

4

2 回答 2

1
  • 您可能需要在控制器的 destroy 方法中删除 eventListener。
  • 为什么要使用全局事件侦听器进行本地事件管理?
  • 也许您可以改用回调

这些只是一些快速观察,无需我编写任何代码来验证。老实说,我根本不使用全局事件。

于 2013-07-09T03:59:42.990 回答
0

这是一个快速修复,实现 Aaron 在他的第一个项目符号中所说的,只需将此方法添加到您的库存行控制器。

// Here is the event listener function
var checkInListenFunction = function(e) {
    console.info('Checking In: ' + args.data.title);
}

// Add just like in your code
Ti.App.addEventListener('checkIn', checkInListenFunction);

// When this controller is destroyed you have to remove the listener as well
// OR the controller will forever stay in memory, since you access variables 
// from the controllers scope!
exports.destroy = function() {
    // Remove the listener first
    Ti.App.addRemoveListener('checkIn', checkInListenFunction);
    $.destroy();
}

全局事件侦听器会持续存在,直到您将它们删除,这意味着(根据 javascript 范围规则)它们访问的任何变量也会自动持续存在。由于您args.data.title在事件侦听器内部访问,并且此变量的作用域为inventory_list_row控制器,因此无论您做什么,解释器都会将控制器(或其中大部分)保留在内存中,因此这些事件将在您销毁和 null 后很长时间内继续触发他们出去。

我根本不会使用全局事件侦听器,在内存稀缺的环境中,太多的范围混淆和内存泄漏的可能性。接受 Aaron 的建议并基于此回调,或在控制器本身上触发本地事件。

编辑:

如果您只希望该侦听器“侦听”一次,则可以这样做,只需立即将其删除,简单:

Ti.App.addEventListener('checkIn', function(e) {
    console.info('Checking In: ' + args.data.title);
    Ti.App.removeEventListener(this);
});
于 2013-07-10T16:57:37.007 回答