Reputation: 57
I would like to understand best practice when removing items that have event listeners attached.
For example:
I have a scrollview that contains a number of child items. I want to refresh the contents of the scrollview with a different list of items.
Each of the items contained in the scrollview has one or more eventlisteners attached.
Should I remove the event listeners before removing the items? or Does removing an item automatically clear any attached event listeners?
I am trying to ensure that I do not affect performance or memory consumption by having active listeners to UI objects that no longer exist.
Upvotes: 1
Views: 209
Reputation: 2735
You should read this.
the JavaScript interpreter sweeps through memory looking for objects to which no references remain. Those are then destroyed to release the memory they were consuming.
If an object is removed from the memory, its event listeners go away as well. You don't need to call removeEventListener() again.
So in your case, removing the child view and making sure there is no other reference to it should be enough.
Upvotes: 2
Reputation: 354
Good Question. Memory is "precious" (done with best Gollum accent) on a mobile device, and creating leaks can definitely be a path to crashes, low star ratings and unhappy users. There are several misconceptions about how garbage collection is handled when adding / removing views and closing windows. Closing windows cleans up subviews, using the .remove()
method actually removes the view from memory, etc.
In this particular use case, since there is not a code example, I'll have to speculate on how your creating your subviews and how your handling and setting up your event listeners, but in general this should apply to most things.
For your view, we'll assume that you have defined a ScrollView (id='scrollView') in your Alloy view file, and your creating your subviews your doing something like this:
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);
}
In the above example, we're doing a few things:
1) We create an array to hold all of our subviews, so if we need to reference a particular view (ahem, for garbage collection) we can
2) We are declaring our event function instead of creating it inline with the event listener, so we can clean it up if needed
Now then - in any use case we're prepared to manage the memory of this particular view.
Now lets say you decide to remove all the views of that particular ScrollView, and you use something like:
$.scrollView.removeAllChildren();
And then go about adding your new views. Did your subviews just go away? What about the event listeners?
The answer - they are still hanging around. Its easy to check, just throw
console.log(subViews.length);
at the end of the code your using to add views (like the above example) and you'll see something like this.
[INFO] 10
[INFO] 20
[INFO] 30
[INFO] 40
[INFO] 50
[INFO] 60
[INFO] 70
So with this information, you should now have a good idea of how to clean up the subViews when your ready to get rid of them. Here is an example how:
function cleanUpSubViews(){
while(subViews.length) {
var v = subViews.pop();
v.removeEventListener('click', _doSomething);
v = null;
};
}
In general, cleaning up the subViews should clear the event Listeners, however to be sure I would recommend adding that one line in the above code to handle it for sure.
You can check out a working example here: https://gist.github.com/grantges/884ae6b2fd8570a89109
And be sure to check out our documentation on Managing Memory, along with our Best Practice Guides to get a bit more information and clarity on this.
Upvotes: 1