Skip to content

Commit

Permalink
some love for documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniil Korostelev committed Jun 19, 2024
1 parent 2de4b52 commit cd9cd0d
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
6 changes: 3 additions & 3 deletions docs/articles/binding-batching.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand All @@ -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).
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).
44 changes: 43 additions & 1 deletion docs/articles/collections-list.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
## Observable List

> TODO: document
`ObservableList<T>` is an observable wrapper around the standard `List<T>`, 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<T> : IList<T>
{
Observable<IReadOnlyList<T>> Observe();
}
```

Like most of observables, `ObservableList<T>` can be created by a static function in the `Observable` helper class:

```csharp
static class Observable
{
static ObservableList<T> List<T>();
}
```

Adding and removing elements will naturally trigger its bindings and propagate through auto-observables.

## Example

```csharp
var list = Observable.List<int>();
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
```

0 comments on commit cd9cd0d

Please sign in to comment.