在销毁控制器后触发的Titanium应用程序事件

时间:2013-07-09 00:21:17

标签: titanium appcelerator titanium-mobile appcelerator-mobile titanium-alloy

  • 申请类型:手机
  • Titanium SDK:3.1.1.GA
  • 平台&版本:iOS 6.1
  • 设备:iOS模拟器
  • 主机操作系统:OSX 10.8.4
  • Titanium Studio: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');

inventory_list_row.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并将行设置为null无效。

2 个答案:

答案 0 :(得分:1)

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

这些只是一些快速的观察,我没有编写任何代码来进行验证。老实说,我根本不使用全球事件。

答案 1 :(得分: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控制器,因此无论您执行什么操作,解释器都会将控制器(或大部分控制器)保留在内存中,因此这些事件在你摧毁并将它们归零后,它会继续射击。

我根本不会使用全局事件侦听器,在内存稀缺的环境中存在太大的范围混淆和内存泄漏的可能性。以Aaron的建议为基础进行回调,或者在控制器本身上发起本地事件。

修改

如果你只想让听众“听”一次,你可以这样做,只需立即删除它,简单:

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