yet_another_observer

Creator: coderz1093

Last updated:

0 purchases

TODO
Add to Cart

Description:

yet another observer

This package lets you observe changes to any variable or expression without having to
use any special types or annotations. This makes it easy to retrofit it into an existing
project where you need to observe something without changing existing variable types.
If you have ever found yourself adding something like _lastValue and if(value != _lastValue)
then this package is for you, and takes care of those details in a nicer way without
polluting your code with variables and if statements.
Features #
This observer relies on manually calling an update method to check for changes to the
observed variables or expressions. This makes it suitable for use in Flutter Widgets,
where the observers can be updated on each build.
There's also a manager class that can be used to simplify managing and updating multiple
observers from one place.
To make it even easier, the package includes an observer Widget that can be used to wrap
other widgets and automatically trigger the update, as well as a mixin that simplifies
managing and updating multiple observers from a StatefulWidget.
Basic usage #
int value = 1;

YAObserver observer = YAObserver(
() => value,
onChanged: (event){
print('value=${event.value}');
},
updateImmediately: true
);

value = 2;
observer.update(); // Prints "value=2"
copied to clipboard
The example above simply checks the result of invoking () => value, compares it to the
previous value, and triggers onChanged if the value was changed.
Events #
Whenever a change of the observed value is detected, the onChanged method of the observer
will be invoked with an event parameter. The event parameter holds information about the change:

value is the current value of the observed value.
changeTime is the time when the change was detected (not necessarily the exact time
when the variables value was changed - it will be the time when the [update] method of
the observer was executed).
history contains a list of past events. The maximum number of historical events to
keep is defined when constructing the observer. The latest historical event will be at
index 0, the one before that at index 1, and so on.

Observing non-scalar values #
1. Getting the value #
The first problem that could arise is that if you supply an object as the value to be observed,
that same object instance could will end up being compared to itself! That's because the
observer stores the previous value and then checks it against the current value on the next
update.
The solution is to always supply a unique instance to the value function. For example, if you want
to observe a List, instead of writing
YAObserver(
() => myList,
onChanged: (event){
// Might never be called, because both the old and current value might point
// to the same list and thus appear (to the observer) to never change.
}
)
copied to clipboard
you could write
YAObserver(
() => myList.toList(),
onChanged: (event){
}
)
copied to clipboard
The example above uses toList() to create a unique instance of the list, which gets stored as
the old value. The next time update() is called, the old value will be different from the
current value. Which brings us to problem nr 2...
2. Comparing previous and current value #
Some special care needs to be taken when observing non-scalar values, for example a List.
The observer will by default use the == operator to compare the previous and the current
observed value.
Consider the following code:
List<String> myList = ['abc'];

YAObserver observer = YAObserver<List<String>>(
() => myList.toList(),
onChanged: (event){
print('The list changed from ${event.history[0].value} to ${event.value}.');
},
maxHistoryLength: 1,
updateImmediately: true,
fireOnFirstUpdate: false
);

myList = ['123'];
observer.update();

myList = ['123'];
observer.update();

myList.add('foobar');
observer.update();

copied to clipboard
This will result in
The list changed from [abc] to [123].
The list changed from [123] to [123].
copied to clipboard
You might have expected that the output would be
The list changed from [abc] to [123].
The list changed from [123] to [123, foobar].
copied to clipboard
The problem is that we're comparing List instances and not their actual contents. This problem can be
solved by supplying a custom hasChanged function to the observer. To achieve the desired result, there
are a number of options.
First, you could convert the List into a scalar value, for example by JSON-encoding it or simply
supplying the observer with the value of myList.toString(). Then you would be comparing strings, which would work.
The problem with this solution is that two lists with the same contents but in different order will
result in two different strings, so they will not be equal.
A better option is to use the Dart collection library, which provides some handy functions for
comparing lists and other collections.
import 'package:collection/collection.dart';

YAObserver observer = YAObserver<List<String>>(
() => myList,
onChanged: (event){
print('The list changed from ${event.history[0].value} to ${event.value}.');
},
hasChanged: (old, current) => ! const ListEquality().equals(old, current),
maxHistoryLength: 1,
updateImmediately: true,
fireOnFirstUpdate: false
);
copied to clipboard
will result in
The list changed from [abc] to [123].
The list changed from [123] to [123, foobar].
copied to clipboard
Additional information #
Check out the example for some more information about what this package can do. Also see the inline
documentation in the code.

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Files:

Customer Reviews

There are no reviews.