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无效。
答案 0 :(得分:1)
这些只是一些快速的观察,我没有编写任何代码来进行验证。老实说,我根本不使用全球事件。
答案 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);
});