Dart DocumentationobserveObservableMap<K, V>

ObservableMap<K, V> class

Represents an observable map of model values. If any items are added, removed, or replaced, then observers that are listening to changes will be notified.

class ObservableMap<K, V> extends ObservableBase implements Map<K, V> {
 static const _LENGTH = const Symbol('length');

 final Map<K, V> _map;

 /** Creates an observable map. */
 ObservableMap() : _map = new HashMap<K, V>();

 /** Creates a new observable map using a [LinkedHashMap]. */
 ObservableMap.linked() : _map = new LinkedHashMap<K, V>();

 /** Creates a new observable map using a [SplayTreeMap]. */
 ObservableMap.sorted() : _map = new SplayTreeMap<K, V>();

 /**
  * Creates an observable map that contains all key value pairs of [other].
  * It will attempt to use the same backing map type if the other map is a
  * [LinkedHashMap], [SplayTreeMap], or [HashMap]. Otherwise it defaults to
  * [HashMap].
  *
  * Note this will perform a shallow conversion. If you want a deep conversion
  * you should use [toObservable].
  */
 factory ObservableMap.from(Map<K, V> other) {
   var result = new ObservableMap<K, V>._createFromType(other);
   other.forEach((key, value) { result[key] = value; });
   return result;
 }

 factory ObservableMap._createFromType(Map<K, V> other) {
   ObservableMap result;
   if (other is SplayTreeMap) {
     result = new ObservableMap<K, V>.sorted();
   } else if (other is LinkedHashMap) {
     result = new ObservableMap<K, V>.linked();
   } else {
     result = new ObservableMap<K, V>();
   }
   return result;
 }

 Iterable<K> get keys => _map.keys;

 Iterable<V> get values => _map.values;

 int get length =>_map.length;

 bool get isEmpty => length == 0;

 bool get isNotEmpty => !isEmpty;

 bool containsValue(Object value) => _map.containsValue(value);

 bool containsKey(Object key) => _map.containsKey(key);

 V operator [](Object key) => _map[key];

 void operator []=(K key, V value) {
   int len = _map.length;
   V oldValue = _map[key];
   _map[key] = value;
   if (hasObservers) {
     if (len != _map.length) {
       notifyPropertyChange(_LENGTH, len, _map.length);
       notifyChange(new MapChangeRecord(key, isInsert: true));
     } else if (!identical(oldValue, value)) {
       notifyChange(new MapChangeRecord(key));
     }
   }
 }

 V putIfAbsent(K key, V ifAbsent()) {
   int len = _map.length;
   V result = _map.putIfAbsent(key, ifAbsent);
   if (hasObservers && len != _map.length) {
     notifyPropertyChange(_LENGTH, len, _map.length);
     notifyChange(new MapChangeRecord(key, isInsert: true));
   }
   return result;
 }

 V remove(Object key) {
   int len = _map.length;
   V result =  _map.remove(key);
   if (hasObservers && len != _map.length) {
     notifyChange(new MapChangeRecord(key, isRemove: true));
     notifyPropertyChange(_LENGTH, len, _map.length);
   }
   return result;
 }

 void clear() {
   int len = _map.length;
   if (hasObservers && len > 0) {
     _map.forEach((key, value) {
       notifyChange(new MapChangeRecord(key, isRemove: true));
     });
     notifyPropertyChange(_LENGTH, len, 0);
   }
   _map.clear();
 }

 void forEach(void f(K key, V value)) => _map.forEach(f);

 String toString() => Maps.mapToString(this);
}

Extends

ObservableBase > ObservableMap<K, V>

Implements

Map<K, V>

Constructors

new ObservableMap() #

Creates an observable map.

ObservableMap() : _map = new HashMap<K, V>();

factory ObservableMap.from(Map<K, V> other) #

Creates an observable map that contains all key value pairs of other. It will attempt to use the same backing map type if the other map is a LinkedHashMap, SplayTreeMap, or HashMap. Otherwise it defaults to HashMap.

Note this will perform a shallow conversion. If you want a deep conversion you should use toObservable.

factory ObservableMap.from(Map<K, V> other) {
 var result = new ObservableMap<K, V>._createFromType(other);
 other.forEach((key, value) { result[key] = value; });
 return result;
}

new ObservableMap.linked() #

Creates a new observable map using a LinkedHashMap.

ObservableMap.linked() : _map = new LinkedHashMap<K, V>();

new ObservableMap.sorted() #

Creates a new observable map using a SplayTreeMap.

ObservableMap.sorted() : _map = new SplayTreeMap<K, V>();

Properties

final Stream<List<ChangeRecord>> changes #

inherited from ObservableBase

The stream of change records to this object.

Changes should be delivered in asynchronous batches by calling queueChangeRecords.

deliverChangeRecords can be called to force delivery.

docs inherited from Observable
Stream<List<ChangeRecord>> get changes {
 if (_broadcastController == null) {
   _broadcastController =
       new StreamController<List<ChangeRecord>>.broadcast(sync: true);
 }
 return _broadcastController.stream;
}

final bool hasObservers #

inherited from ObservableBase

True if this object has any observers, and should call notifyPropertyChange for changes.

bool get hasObservers => _broadcastController != null &&
                        _broadcastController.hasListener;

final bool isEmpty #

Returns true if there is no {key, value} pair in the map.

docs inherited from Map<K, V>
bool get isEmpty => length == 0;

final bool isNotEmpty #

Returns true if there is at least one {key, value} pair in the map.

docs inherited from Map<K, V>
bool get isNotEmpty => !isEmpty;

final Iterable<K> keys #

The keys of this.

docs inherited from Map<K, V>
Iterable<K> get keys => _map.keys;

final int length #

The number of {key, value} pairs in the map.

docs inherited from Map<K, V>
int get length =>_map.length;

final Iterable<V> values #

The values of this.

docs inherited from Map<K, V>
Iterable<V> get values => _map.values;

Operators

V operator [](Object key) #

Returns the value for the given key or null if key is not in the map. Because null values are supported, one should either use containsKey to distinguish between an absent key and a null value, or use the putIfAbsent method.

docs inherited from Map<K, V>
V operator [](Object key) => _map[key];

void operator []=(K key, V value) #

Associates the key with the given value.

docs inherited from Map<K, V>
void operator []=(K key, V value) {
 int len = _map.length;
 V oldValue = _map[key];
 _map[key] = value;
 if (hasObservers) {
   if (len != _map.length) {
     notifyPropertyChange(_LENGTH, len, _map.length);
     notifyChange(new MapChangeRecord(key, isInsert: true));
   } else if (!identical(oldValue, value)) {
     notifyChange(new MapChangeRecord(key));
   }
 }
}

Methods

abstract void addAll(Map<K, V> other) #

inherited from Map

Adds all key-value pairs of other to this map.

If a key of other is already in this map, its value is overwritten.

The operation is equivalent to doing this[key] = value for each key and associated value in other. It iterates over other, which must therefore not change during the iteration.

void clear() #

Removes all pairs from the map.

docs inherited from Map<K, V>
void clear() {
 int len = _map.length;
 if (hasObservers && len > 0) {
   _map.forEach((key, value) {
     notifyChange(new MapChangeRecord(key, isRemove: true));
   });
   notifyPropertyChange(_LENGTH, len, 0);
 }
 _map.clear();
}

bool containsKey(Object key) #

Returns whether this map contains the given key.

docs inherited from Map<K, V>
bool containsKey(Object key) => _map.containsKey(key);

bool containsValue(Object value) #

Returns whether this map contains the given value.

docs inherited from Map<K, V>
bool containsValue(Object value) => _map.containsValue(value);

void forEach(void f(K key, V value)) #

Applies f to each {key, value} pair of the map.

It is an error to add or remove keys from the map during iteration.

docs inherited from Map<K, V>
void forEach(void f(K key, V value)) => _map.forEach(f);

void notifyChange(ChangeRecord record) #

inherited from ObservableBase

Notify observers of a change. For most objects notifyPropertyChange is more convenient, but collections sometimes deliver other types of changes such as a ListChangeRecord.

void notifyChange(ChangeRecord record) {
 if (!hasObservers) return;

 if (_changes == null) {
   _changes = [];
   queueChangeRecords(_deliverChanges);
 }
 _changes.add(record);
}

dynamic notifyPropertyChange(Symbol field, Object oldValue, Object newValue) #

inherited from ObservableBase

Notify that the field name of this object has been changed.

The oldValue and newValue are also recorded. If the two values are identical, no change will be recorded.

For convenience this returns newValue. This makes it easy to use in a setter:

var _myField;
get myField => _myField;
set myField(value) {
  _myField = notifyPropertyChange(
      const Symbol('myField'), _myField, value);
}
notifyPropertyChange(Symbol field, Object oldValue, Object newValue) {
 if (hasObservers && !identical(oldValue, newValue)) {
   notifyChange(new PropertyChangeRecord(field));
 }
 return newValue;
}

V putIfAbsent(K key, V ifAbsent()) #

If key is not associated to a value, calls ifAbsent and updates the map by mapping key to the value returned by ifAbsent. Returns the value in the map.

It is an error to add or remove keys from map during the call to ifAbsent.

docs inherited from Map<K, V>
V putIfAbsent(K key, V ifAbsent()) {
 int len = _map.length;
 V result = _map.putIfAbsent(key, ifAbsent);
 if (hasObservers && len != _map.length) {
   notifyPropertyChange(_LENGTH, len, _map.length);
   notifyChange(new MapChangeRecord(key, isInsert: true));
 }
 return result;
}

V remove(Object key) #

Removes the association for the given key. Returns the value for key in the map or null if key is not in the map. Note that values can be null and a returned null value does not always imply that the key is absent.

docs inherited from Map<K, V>
V remove(Object key) {
 int len = _map.length;
 V result =  _map.remove(key);
 if (hasObservers && len != _map.length) {
   notifyChange(new MapChangeRecord(key, isRemove: true));
   notifyPropertyChange(_LENGTH, len, _map.length);
 }
 return result;
}

String toString() #

Returns a string representation of this object.

docs inherited from Object
String toString() => Maps.mapToString(this);