1

我希望瞭解刪除附加了事件偵聽器的項目時的最佳做法。最佳實踐確認:刪除EventListeners

例如:

我有一個包含許多子項的滾動視圖。我想用不同的項目列表來刷新滾動視圖的內容。

滾動視圖中包含的每個項目都附有一個或多個事件監聽器。

我應該在刪除項目之前刪除事件偵聽器嗎? 或 刪除項目是否會自動清除所有附加的事件偵聽器?

我試圖通過讓不再存在的UI對象的活動偵聽器來影響性能或內存消耗。

回答

1

好問題。記憶在移動設備上是「珍貴的」(用最好的咕嚕口音完成),而創建泄漏肯定會成爲崩潰,低星級和不滿意用戶的途徑。關於在添加/刪除視圖和關閉窗口時如何處理垃圾收集有幾個誤解。關閉窗口清理子視圖,使用.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拿到這個更多的信息和清晰度。

+0

伯特, 感謝您的詳細回覆。 問題的主要原因是這是一個跨平臺的解決方案(iOS,Android和MobileWeb),目前在MobileWeb中不支持removeAllChildren。 因此,我們正在尋找手動刪除項目。 在可能的情況下,我們將刪除容器滾動視圖並重新構建它,而不是遍歷子項並將其移除。 我試圖確定是否(在刪除父窗口中),我可以避免刪除所有的孩子,並且,因爲他們有事件監聽器也將它們全部刪除。 – theThought

+0

更詳細地閱讀了您的回覆。我可以看到手動刪除父滾動視圖是不夠的。所以我正在修改我的代碼以確保所有子視圖(及其事件偵聽器)都被刪除。 – theThought

+0

如果沒有其他對父視圖和子視圖的引用,則刪除父視圖就足夠了。在Bert的例子中,子視圖存儲在數組中。這就是爲什麼你必須從數組中刪除它們(只有'subViews = null')。另外,不需要'v.removeEventListener'和'v = null'。在下面檢查我的答案。 – Shawn

2

您應該閱讀this

JavaScript解釋器掃過內存尋找沒有引用保留的對象。那些被破壞釋放他們消耗的內存。

如果一個對象從內存中刪除,其事件偵聽器也會消失。您不需要再次調用removeEventListener()。

所以在你的情況下,刪除子視圖,並確保沒有其他引用它應該就足夠了。