我希望瞭解刪除附加了事件偵聽器的項目時的最佳做法。最佳實踐確認:刪除EventListeners
例如:
我有一個包含許多子項的滾動視圖。我想用不同的項目列表來刷新滾動視圖的內容。
滾動視圖中包含的每個項目都附有一個或多個事件監聽器。
我應該在刪除項目之前刪除事件偵聽器嗎? 或 刪除項目是否會自動清除所有附加的事件偵聽器?
我試圖通過讓不再存在的UI對象的活動偵聽器來影響性能或內存消耗。
我希望瞭解刪除附加了事件偵聽器的項目時的最佳做法。最佳實踐確認:刪除EventListeners
例如:
我有一個包含許多子項的滾動視圖。我想用不同的項目列表來刷新滾動視圖的內容。
滾動視圖中包含的每個項目都附有一個或多個事件監聽器。
我應該在刪除項目之前刪除事件偵聽器嗎? 或 刪除項目是否會自動清除所有附加的事件偵聽器?
我試圖通過讓不再存在的UI對象的活動偵聽器來影響性能或內存消耗。
好問題。記憶在移動設備上是「珍貴的」(用最好的咕嚕口音完成),而創建泄漏肯定會成爲崩潰,低星級和不滿意用戶的途徑。關於在添加/刪除視圖和關閉窗口時如何處理垃圾收集有幾個誤解。關閉窗口清理子視圖,使用.remove()
方法實際上從內存中刪除視圖等。
在這個特殊的用例中,由於沒有代碼示例,我將不得不猜測如何創建子視圖和你如何處理和設置事件監聽器,但總的來說,這應該適用於大多數事情。
對於您的觀點,我們假設你已經在你的合金視圖文件中定義的滾動型(ID =「滾動視圖」),以及您創建的子視圖您做這樣的事情:
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)我們正在聲明我們的事件函數,而不是在inli中創建它ne的事件監聽器,所以我們可以清理它,如果需要的話
然後 - 在任何使用情況下,我們準備管理這個特定視圖的內存。
現在讓我們假設你決定刪除該特定滾動型的各方面的意見,並使用類似:
$.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拿到這個更多的信息和清晰度。
您應該閱讀this。
JavaScript解釋器掃過內存尋找沒有引用保留的對象。那些被破壞釋放他們消耗的內存。
如果一個對象從內存中刪除,其事件偵聽器也會消失。您不需要再次調用removeEventListener()。
所以在你的情況下,刪除子視圖,並確保沒有其他引用它應該就足夠了。
伯特, 感謝您的詳細回覆。 問題的主要原因是這是一個跨平臺的解決方案(iOS,Android和MobileWeb),目前在MobileWeb中不支持removeAllChildren。 因此,我們正在尋找手動刪除項目。 在可能的情況下,我們將刪除容器滾動視圖並重新構建它,而不是遍歷子項並將其移除。 我試圖確定是否(在刪除父窗口中),我可以避免刪除所有的孩子,並且,因爲他們有事件監聽器也將它們全部刪除。 – theThought
更詳細地閱讀了您的回覆。我可以看到手動刪除父滾動視圖是不夠的。所以我正在修改我的代碼以確保所有子視圖(及其事件偵聽器)都被刪除。 – theThought
如果沒有其他對父視圖和子視圖的引用,則刪除父視圖就足夠了。在Bert的例子中,子視圖存儲在數組中。這就是爲什麼你必須從數組中刪除它們(只有'subViews = null')。另外,不需要'v.removeEventListener'和'v = null'。在下面檢查我的答案。 – Shawn