Git Product home page Git Product logo

observable's Introduction

Build Status

Support for detecting and being notified when an object is mutated.

An observable is a way to be notified of a continuous stream of events over time.

Some suggested uses for this library:

  • Observe objects for changes, and log when a change occurs
  • Optimize for observable collections in your own APIs and libraries instead of diffing
  • Implement simple data-binding by listening to streams

You may want to look at the former TC39 proposal Observe.observe, which was deprecated.

Usage

There are two general ways to detect changes:

  • Listen to Observable.changes and be notified when an object changes
  • Use Differ.diff to determine changes between two objects

observable's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

observable's Issues

Null safety

It seems the master branch is already upgrade to null safety. Is it ready to publish on pub?

Discuss: Minimize `Observable` interface into...

/// Represents an object with observable state or properties.
///
/// The interface does not require any specific technique to implement
/// observability. You may implement it in the following ways:
///
/// - Extend or mixin [ObservableChangeNotifier] or [ObservableStateNotifier]
/// - Implement the interface yourself and provide your own implementation
abstract class Observable<C extends ChangeRecord> {
  /// Emits a list of changes when the state of the object changes.
  ///
  /// Changes should produced in order, if significant.
  Stream<List<C>> get changes;
}

Please update to support dart 2.9.0-5.0.dev

Please update to support dart 2.9.0-5.0.dev

due to this angulardart/angular#1891
ย  problem I had to upgrade to dart 2.9 Angular 6 is working correctly without angular_components
Due to this

Because observable> = 0.1.1 <= 0.22.1 + 3 requires SDK version <2.0.0 or> = 2.0.0-dev.23.0 <2.0.0 and angular_components> = 0.9.0-beta + 1 <0.13.0 depends on observable ^ 0.22.1 + 3, angular_components> = 0.9.0-beta + 1 <0.13.0 requires observable ^ 0.22.1 + 4.
And because angular_components <0.9.0-beta + 1 requires SDK version> = 1.22.0 <2.0.0-โˆž, angular_components <0.13.0 requires observable ^ 0.22.1 + 4.
And because angular_components> = 0.13.0 depends on observable ^ 0.22.2 which depends on dart_internal ^ 0.1.1, every version of angular_components requires dart_internal ^ 0.1.1.
So, because dart_internal> = 0.1.1 requires SDK version> = 2.0.0-dev.12.0 <2.9.0 and angular_form_bug depends on angular_components any, version solving failed.

ObservableList's change not being listened to

Minimal Reproduction

pubspec.yaml:

name: observable_demo

dependencies:
  observable: ^0.24.0

Dart:

import 'package:observable/observable.dart';

void main() {
  var obs = ObservableList.from(["first value"]);
  obs.changes.listen(([value = ""]) {
    print(value);
  });
  obs[0] = "second valuee";
}

Expected Behavior

Print:

second valuee

Current Behavior

Prints nothing.

Dart 2 runtime errors in tests

running tests in dart 2 mode,

type 'SubListIterable' is not a subtype of type 'Iterable' of 'iterable' where...
type 'SubListIterable' is not a subtype of type 'Iterable' of 'iterable' where
SubListIterable is from dart:_internal
String is from dart:core
Iterable is from dart:core
Null is from dart:core
dart:core List.insertAll
../../observable/lib/src/differs/list_differ.dart 366:19 _mergeSplices
../../observable/lib/src/differs/list_differ.dart 423:5 _createInitialSplices
../../tobservable/lib/src/differs/list_differ.dart 448:26 projectListSplices
package:observable/src/observable_list.dart 335:21 ObservableList.deliverListChanges
===== asynchronous gap ===========================
dart:async scheduleMicrotask
package:observable/src/observable_list.dart 312:7 ObservableList._notifyListChange
package:observable/src/observable_list.dart 233:7 ObservableList.removeRange
../../observable/test/list_change_test.dart 134:13 listChangeTests..

Option to supply equality comparer in ObservableList

ObservableList normalizes change records before sending the change event
https://github.com/dart-lang/observable/blob/5cb19656f0809b961a328b8f7054a0eb14071978/lib/src/observable_list.dart#L330
The actual work is done by the utility function projectListSplices, which has an optional equality parameter, but this parameter is not used by ObservableList. It would be nice to be able to control the equality comparer used for the sake of determining if the elements are equal. I imagine that an optional equality comparer parameter would be added to some of the constructors of ObservableList.

In my particular use case, I expect reference equality semantics for the purpose of determining whether the list has changed, but the concrete item type has an overridden equality operator to perform deep comparison.

deliveryChanges does not work with Dart2 (with solution)

Extend ChangeNotifier with your own ChangeRecord, like:

class MyRecord extends ChangeRecord {
}
class MyClass extends ChangeNotifier<MyRecord> {
}

once you add some notifications, dart throws an error on:

bool deliverChanges() {
    List<ChangeRecord> changes;
    ...
    _changes.add(changes); // this will throw an error of mismatched types
}

The only thing you need to do to solve it is change this line:

bool deliverChanges() {
    List<ChangeRecord> changes;

to this:

bool deliverChanges() {
    List<C> changes;

Write a CHANGELOG for 0.21.0

From my comment on #50:

We'll be kicking ourselves in a week or a few if we don't get pedantic here: even though it will take a bit of work, I would want:

  • What are the bullets from the CHANGELOG that are being reverted?
  • What new fixes made it into the internal branch that are being introduced here, one by one?
  • Why is the minimum SDK 2.0.0-dev.22.0?

List change never firing, this prints nothing

    var mydata = JSON.decode("""
    [{
    "title" : "my title",
    "text" : "my text"
    },
    {
    "title" : "my title 2",
    "text" : "my text 2"
    }]""");
    var observe = new ObservableList.from(mydata);
    observe.changes.listen((e) {
      print("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
    });
    mydata.removeAt(1);

Confusing doc / inconsistent implementation

After spending some time trying to replace our internal implementation with ObservableList from this package, I decided to summarize my experience here. Indeed, the semantics are slightly different and I might be confusing use cases, but I found a lot of places over the code base where it looks like this package is in the process of refactoring, yet there is very little recent activity.

  • documentation suggests using PropertyChangeMixin which does not exist (reverted in #14). The only working way I found is:
    class MyNumbers extends ObservableList<int>
        with
            ChangeNotifier<ChangeRecord>,
            // ignore: mixin_inherits_from_not_object
            PropertyChangeNotifier {}
  • the above is further reinforced by the lack of a test on observed() / unobserved(), and a test of mixing ChangeNotifier into Observable
  • documentation insists that "ObservableList will only emit on ObservableList.changes, instead of on ObservableList.listChanges", yet it does not look even close to that:
    • listChanges is not marked deprecated;
    • list change events (addition/removal) are not delivered to changes;
    • changes interface is not ready to handle both Property change and List change types (for instance, there's no event filtering mechanism). ObservableMap simply reports all events to changes without filtering - is the stream listener supposed to filter with if (event is MapChangeRecord)?
  • the code does not give an opportunity to implement observed / unobserved for listChanges (there's a TODO mentioning that), which makes it challenging to implement e.g. self-disposable BLoC with StreamBuilder in Flutter. Not filing a separate issue for it, because in the light of listChanges getting removed (?) this might become invalid.

That's it for now; I'll appreciate feedback on what of the above is valid and needs a fix, or where I misunderstood the intention.

+cc @matanlurey in case they'd be interested in resuming the great work started in #11.

UPD 1: added necessary lint ignore in PropertyChangeNotifier snippet.

Implementation of cast methods allows mutation without notifications.

Changes on ObservableMap and ObservableList objects created via cast or castFrom mutate the original collections but do not trigger notifications on the original collections.

final original = ObservableList<int>.from([1, 2, 3]);
original.changes.listen(print); // Listener never triggered.
final cast = original.cast<num>();
cast.add(4);
print(original); // Prints [1, 2, 3, 4].
await Future(() {}); // Flush any microtasks.

Internal: ObservableList#listChanges still regressing

It should never emit ChangeRecord.ANY:

Change required internally:

  @override
  Stream<List<ListChangeRecord<E>>> get listChanges {
    return _listChanges.changes
        .map((r) => projectListSplices(this, r))
        .where((r) => r.isNotEmpty && r != ChangeRecord.ANY);  // <--                                   
  }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.