Fix memory leak when removing layers from ol.layer.Group

Fixes #3479
This commit is contained in:
Frederic Junod
2015-04-09 11:43:44 +02:00
parent 8b95ea4fbc
commit 486a329cb4
+37 -21
View File
@@ -48,9 +48,15 @@ ol.layer.Group = function(opt_options) {
/** /**
* @private * @private
* @type {Object.<string, goog.events.Key>} * @type {Array.<goog.events.Key>}
*/ */
this.listenerKeys_ = null; this.layersListenerKeys_ = [];
/**
* @private
* @type {Object.<string, Array.<goog.events.Key>>}
*/
this.listenerKeys_ = {};
goog.events.listen(this, goog.events.listen(this,
ol.Object.getChangeEventType(ol.layer.GroupProperty.LAYERS), ol.Object.getChangeEventType(ol.layer.GroupProperty.LAYERS),
@@ -89,28 +95,31 @@ ol.layer.Group.prototype.handleLayerChange_ = function() {
* @private * @private
*/ */
ol.layer.Group.prototype.handleLayersChanged_ = function(event) { ol.layer.Group.prototype.handleLayersChanged_ = function(event) {
if (!goog.isNull(this.listenerKeys_)) { goog.array.forEach(this.layersListenerKeys_, goog.events.unlistenByKey);
goog.array.forEach( this.layersListenerKeys_.length = 0;
goog.object.getValues(this.listenerKeys_), goog.events.unlistenByKey);
this.listenerKeys_ = null;
}
var layers = this.getLayers(); var layers = this.getLayers();
this.listenerKeys_ = { this.layersListenerKeys_.push(
'add': goog.events.listen(layers, ol.CollectionEventType.ADD, goog.events.listen(layers, ol.CollectionEventType.ADD,
this.handleLayersAdd_, false, this), this.handleLayersAdd_, false, this),
'remove': goog.events.listen(layers, ol.CollectionEventType.REMOVE, goog.events.listen(layers, ol.CollectionEventType.REMOVE,
this.handleLayersRemove_, false, this) this.handleLayersRemove_, false, this));
};
goog.object.forEach(this.listenerKeys_, function(keys) {
goog.array.forEach(keys, goog.events.unlistenByKey);
});
goog.object.clear(this.listenerKeys_);
var layersArray = layers.getArray(); var layersArray = layers.getArray();
var i, ii, layer; var i, ii, layer;
for (i = 0, ii = layersArray.length; i < ii; i++) { for (i = 0, ii = layersArray.length; i < ii; i++) {
layer = layersArray[i]; layer = layersArray[i];
this.listenerKeys_[goog.getUid(layer).toString()] = this.listenerKeys_[goog.getUid(layer).toString()] = [
goog.events.listen(layer, goog.events.listen(layer, ol.ObjectEventType.PROPERTYCHANGE,
[ol.ObjectEventType.PROPERTYCHANGE, goog.events.EventType.CHANGE], this.handleLayerChange_, false, this),
this.handleLayerChange_, false, this); goog.events.listen(layer, goog.events.EventType.CHANGE,
this.handleLayerChange_, false, this)
];
} }
this.changed(); this.changed();
@@ -123,9 +132,15 @@ ol.layer.Group.prototype.handleLayersChanged_ = function(event) {
*/ */
ol.layer.Group.prototype.handleLayersAdd_ = function(collectionEvent) { ol.layer.Group.prototype.handleLayersAdd_ = function(collectionEvent) {
var layer = /** @type {ol.layer.Base} */ (collectionEvent.element); var layer = /** @type {ol.layer.Base} */ (collectionEvent.element);
this.listenerKeys_[goog.getUid(layer).toString()] = goog.events.listen( var key = goog.getUid(layer).toString();
layer, [ol.ObjectEventType.PROPERTYCHANGE, goog.events.EventType.CHANGE], goog.asserts.assert(!(key in this.listenerKeys_),
this.handleLayerChange_, false, this); 'listeners already registered');
this.listenerKeys_[key] = [
goog.events.listen(layer, ol.ObjectEventType.PROPERTYCHANGE,
this.handleLayerChange_, false, this),
goog.events.listen(layer, goog.events.EventType.CHANGE,
this.handleLayerChange_, false, this)
];
this.changed(); this.changed();
}; };
@@ -137,7 +152,8 @@ ol.layer.Group.prototype.handleLayersAdd_ = function(collectionEvent) {
ol.layer.Group.prototype.handleLayersRemove_ = function(collectionEvent) { ol.layer.Group.prototype.handleLayersRemove_ = function(collectionEvent) {
var layer = /** @type {ol.layer.Base} */ (collectionEvent.element); var layer = /** @type {ol.layer.Base} */ (collectionEvent.element);
var key = goog.getUid(layer).toString(); var key = goog.getUid(layer).toString();
goog.events.unlistenByKey(this.listenerKeys_[key]); goog.asserts.assert(key in this.listenerKeys_, 'no listeners to unregister');
goog.array.forEach(this.listenerKeys_[key], goog.events.unlistenByKey);
delete this.listenerKeys_[key]; delete this.listenerKeys_[key];
this.changed(); this.changed();
}; };