diff --git a/docs/articles/binding-batching.md b/docs/articles/binding-batching.md index 95b5dde..dadd33f 100644 --- a/docs/articles/binding-batching.md +++ b/docs/articles/binding-batching.md @@ -2,9 +2,9 @@ The binding mechanism is designed to support *batching*. This means that the binding callbacks are not executed directly when an observable value is changed, instead they are scheduled for execution all together in a batch once per *frame*. -This makes a lot of sense for updating views: after the business-logic is done with updating observable data, the bindings for changed values are executed in a batch before the next UI redraw happens. +The separation of binding execution makes a lot of sense for updating views: after the business-logic is done with updating observable data, the bindings for changed values are executed in a batch before the next UI redraw happens. It can also have a positive effect on application stability, because, binding callback side-effects, including exceptions, will not interfere with the business-logic that changes the data. -This approach has a nice effect that a binding is only invoked once per changed observable, even if you actually set values multiple times during frame. Even more so, if the final value is unchanged after all assignments and/or recomputations - the binding will not be invoked at all! +Another nice effect is that a binding is only invoked once per changed observable, even if you actually set values multiple times during frame. Even more so, if the final value is unchanged after all assignments and/or recomputations - the binding will not be invoked at all. This is a good optimization and is what we want in most cases, however sometimes we want to make our bindings executed directly. Luckily we can control this by providing the `scheduler` argument to the `Bind` method and using `Scheduler.Direct` instance: @@ -21,4 +21,4 @@ The scheduling mechanism obviously depends on the run-time environment the libra TinkState# provides a batching scheduler implementation for the [Unity](https://unity.com/) game engine out of the box. See the [respective article](unity.md) for more details. -In any other environment, the direct scheduler will be used by default, meaning that all bindings will be executed directly. Thankfully it's pretty easy to plug in a custom scheduler. To do that, one should implement the [`Scheduler`](xref:TinkState.Scheduler) interface and assign an instance of the implementation to `Observable.Scheduler` at start (before doing any bindings). \ No newline at end of file +In any other environment, the direct scheduler will be used by default, meaning that all bindings will be executed directly. Thankfully it's pretty easy to plug in a custom scheduler. To do that, one should implement the [`Scheduler`](xref:TinkState.Scheduler) interface and assign an instance of the implementation to `Observable.Scheduler` at start (before doing any bindings). diff --git a/docs/articles/collections-list.md b/docs/articles/collections-list.md index f2aca25..cbf2975 100644 --- a/docs/articles/collections-list.md +++ b/docs/articles/collections-list.md @@ -1,3 +1,45 @@ ## Observable List -> TODO: document +`ObservableList` is an observable wrapper around the standard `List`, providing the same API for managing the collection. + +In addition to the standard list method, it provides the [`Observe`](xref:TinkState.ObservableList`1.Observe) method to expose itself +as a read-only observable so one can bind to it and react to its changes. + +```csharp +interface ObservableList : IList +{ + Observable> Observe(); +} +``` + +Like most of observables, `ObservableList` can be created by a static function in the `Observable` helper class: + +```csharp +static class Observable +{ + static ObservableList List(); +} +``` + +Adding and removing elements will naturally trigger its bindings and propagate through auto-observables. + +## Example + +```csharp +var list = Observable.List(); +list.Add(1); +list.Add(2); + +var auto = Observable.Auto(() => list.Sum()); +Console.WriteLine(auto.Value); // 3 + +// initial binding prints 1, 2 +list.Observe().Bind(readOnlyList => +{ + foreach (var item in readOnlyList) Console.WriteLine(item); +}); + +list.Add(3); // binding prints 1, 2, 3 + +Console.WriteLine(auto.Value); // 6 +```