lazyData<T> method
Keeps track of some data that can be stateful. You may set the value of returned ValueWrapper both:
- Outside of the build, like a normal call to
setState
- Inside of the build, to use its value inside build
This is a more powerful alternative to lazyState.
Implementation
ValueWrapper<T> lazyData<T>(T Function() init) {
// Create a place to store the data, which should be lazily initialized
final dataWrapper = use.callonce(() => _LazyMutable(init));
// Create a getter on first build, but allow it to be changed
final getterWrapper = use.callonce(() {
return _Mutable(() => dataWrapper.value);
});
// Keep the same setter between builds to prevent unnecessary rebuilds
final setter = use.register((api) {
return (T newState) {
api.rebuild((_) => dataWrapper.value = newState);
};
});
// If the data has changed, then we need to recreate the getter
// NOTE: https://github.com/GregoryConrad/rearch-dart/issues/277
final lastSeenDataWrapper = use.callonce(() {
// NOTE: We want to compare against something that definitely isn't equal
// the first time the state has been mutated.
// Thus, we use a private const object (const _Nothing()),
// since that is guaranteed to be equal to nothing else.
return _Mutable<Object?>(const _Nothing());
});
final hasDataChanged = dataWrapper.hasBeenMutated &&
dataWrapper.value != lastSeenDataWrapper.value;
if (hasDataChanged) {
getterWrapper.value = () => dataWrapper.value;
lastSeenDataWrapper.value = dataWrapper.value;
}
return (getterWrapper.value, setter);
}