Created
November 16, 2018 13:38
-
-
Save brianegan/ad83f7bc2ce63976145596ab8cb51f7b to your computer and use it in GitHub Desktop.
ComputedValueNotifier concept
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/foundation.dart'; | |
/// A class that can be used to derive a value based on data from another | |
/// Listenable or Listenables. | |
/// | |
/// The value will be recomputed when the provided [listenable] notifies the | |
/// listeners that values have changed. | |
/// | |
/// ### Simple Example | |
/// | |
/// ```dart | |
/// final email = ValueNotifier<String>('a'); | |
/// | |
/// // Determine whether or not the email is valid using a (hacky) validator. | |
/// final emailValid = ComputedValueNotifier( | |
/// email, | |
/// () => email.value.contains('@'), | |
/// ); | |
/// | |
/// // The function provided to ComputedValueNotifier is immediately executed, | |
/// // and the computed value is available synchronously. | |
/// print(emailValid); // prints 'false'. | |
/// | |
/// // When the email ValueNotifier is changed, the function will be run again! | |
/// email.value = '[email protected]'; | |
/// print(emailValid); // prints 'true'. | |
/// ``` | |
/// | |
/// ### Deriving data from multiple listenables | |
/// | |
/// In this case, we can use the `Lisetenable.merge` function provided by | |
/// Flutter to merge several variables. | |
/// | |
/// ```dart | |
/// final email = ValueNotifier<String>(''); | |
/// final password = ValueNotifier<String>(''); | |
/// | |
/// // Determine whether the email is valid, and make that a Listenable! | |
/// final emailValid = ComputedValueNotifier<bool>( | |
/// email, | |
/// () => email.value.contains('@'), | |
/// ); | |
/// | |
/// // Determine whether the password is valid, and make that a Listenable! | |
/// final passwordValid = ComputedValueNotifier<bool>( | |
/// password, | |
/// () => password.value.length >= 6, | |
/// ); | |
/// | |
/// // Now, we will only enable the "Login Button" when the email and | |
/// // password are valid. To do so, we can listen to the emailValid and | |
/// // passwordValid ComputedValueNotifiers. | |
/// final loginButtonEnabled = ComputedValueNotifier<bool>( | |
/// Listenable.merge([emailValid, passwordValid]), | |
/// () => emailValid.value && passwordValid.value, | |
/// ); | |
/// | |
/// // Update the email | |
/// print(emailValid.value); // false | |
/// print(loginButtonEnabled.value); // false | |
/// email.value = '[email protected]'; | |
/// print(emailValid.value); // true | |
/// print(loginButtonEnabled.value); // false | |
/// | |
/// // Update the password | |
/// print(passwordValid.value); // false | |
/// password.value = '123456'; | |
/// print(passwordValid.value); // true | |
/// print(loginButtonEnabled.value); // true | |
/// ``` | |
class ComputedValueNotifier<T> extends ChangeNotifier | |
implements ValueListenable { | |
final Listenable listenable; | |
final T Function() compute; | |
T value; | |
ComputedValueNotifier(this.listenable, this.compute) { | |
_updateValue(); | |
listenable.addListener(_updateValue); | |
} | |
@override | |
void dispose() { | |
listenable.removeListener(_updateValue); | |
super.dispose(); | |
} | |
void _updateValue() { | |
value = compute(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment