Repository navigation
Performance API refactor #215
Description
Activity
- addedframeworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.
on Nov 9, 2015 and Simulations too!
- addedc: contributor-productivityTeam-specific productivity, code health, technical debt.Team-specific productivity, code health, technical debt.
on Dec 2, 2015 PerformanceView should lose updateVariable and curveDirection.
AnimatedValue should lose its curves. Instead it takes a PerformanceView, begin, and end, and just asks the performance view it's given for its progress and linearly lerps from begin to end with that value.
Curves are then done as new classes that implement PerformanceView and take a PerformanceView. One of these classes would just apply a curve to the parent's value, forwarding all other calls through. Another would take two curves and remember what direction it's going in.
Transitions would just take one argument, not a performanceview and a variable.- changed the title
[-] Curve and Performance should expose the same API[/-][+]Performance API refactor[/+]on Dec 2, 2015 Some ideas:
abstract class Watchable { void addListener(...); void removeListener(...); void addStatusListener(...); void removeStatusListener(...); Status get status; Direction get direction; } abstract class HasProgress extends Watchable { double get progress; void attach(Attachable child) { child._setParent(this); } } abstract class Attachable { HasProgress get parent => _parent; HasProgress _parent; void _setParent(HasProgress parent) { assert(!attached); _parent = parent; } bool get attached => _parent != null; } abstract class HasValue<T> { T get value; } // concrete classes class AController with HasProgress { // owns a ticker, simulation, etc // play, forward, reverse, fling, etc // progress updated by ticker } class ACurve with HasProgress, Attachable { // curve, reverseCurve double get progress => parent.progress adjusted by relevant curve; } class AValue<T extends dynamic> with Watchable, Attachable implements HasValue<T> { // begin, end T get value => lerp(parent.progress, begin, end); } class ARectValue with Watchable, Attachable implements HasValue<Rect> { // begin, end Rect get value => Rect.lerp(parent.progress, begin, end); } class ADoubleValue with HasProgress, Attachable implements HasValue<double> { // begin, end double get value => lerpDouble(parent.progress, begin, end); double get progress => value; }
So:
class ProgressIndicatorAppState extends State<ProgressIndicatorApp> { void initState() { super.initState(); valueController = new AController(duration: const Duration(milliseconds: 1500)); valueAnimation = valueController.attach(new ACurve( curve: const Interval(0.0, 0.9, curve: Curves.ease), reverseCurve: Curves.ease )).attach(new ADoubleValue( begin: 0.0, end: 1.0 )); valueController.addStatusListener((PerformanceStatus status) { if (status == PerformanceStatus.dismissed || status == PerformanceStatus.completed) reverseValueAnimationDirection(); }); valueController.play(valueAnimationDirection); } // ... // use valueAnimation.value to get the current value in the build functionThe plan is to try implementing the suggestion above and then comparing it to the approach in #1078 to make a decision on how to proceed.
I'm a little unsure about the handling of direction in the current APIs. Direction makes sense for things that are driven by time, but if the driver is arbitrary, then direction makes less sense. I.e. you could have a Curve that maps randomly distributed inputs to randomly distributed outputs and still have the notion of "shape", but "direction" is kind of meaningless.
I believe Performance is the earliest part of the class hierarchy where time is introduced, so I'm wondering if direction as a concept should be removed from everything above it (i.e. removed from PerformanceView, and by virtue of the new inheritance strategy, from Curve).
Interesting idea. We should look at the clients of PerformanceView to see how many of them care about direction. The hero transitions do (in order to decide which heros to select). I'm not sure what else cares.
One big use of direction is having a different curve when going forward
than going backward. The other big use is knowing if you've reached the
"dismissed" state vs the "completed" state (though that's built into
Performance itself).On Mon, Jan 11, 2016 at 3:35 PM Adam Barth [email protected] wrote:
Interesting idea. We should look at the clients of PerformanceView to see
how many of them care about direction. The hero transitions do (in order to
decide which heros to select). I'm not sure what else cares.—
Reply to this email directly or view it on GitHub
#215 (comment).I'm looking at these APIs at the moment with an eye toward having a PerformanceView that's driven by input events. In that context it's a little unclear why direction is useful. You reach the dismissed state if you end at 0.0 progress and the completed state if you end at 1.0 progress, but in the middle you might drift back and forth. In that context having two different curves for going forward vs. backward is a little weird because you would (in the general case) have two different possible outputs for a given mid-interval input, so you'd get discontinuities if you switched back and forth.
Note, I'm not saying the use cases you mention aren't valuable, just that they're not necessarily universal; so they would go better in subclass(es) than base class(es).
As implemented, you never switch curves in the middle. You only switch curves if you hit the end.
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.- locked as resolved and limited conversation to collaborators
on Aug 17, 2021
Wednesday Oct 21, 2015 at 16:48 GMT
Originally opened as https://github.com/flutter/engine/issues/1708
An AnimatedPerformance is a ticker plus forward()/reverse() methods, and exposes a value in the range 0..1 plus a direction and a change notification API.
A Curve should just be something that takes a value in the range 0..1 plus a direction and a change notification API, and exposes a value in the range 0..1 plus a direction and a change notification API (that it transparently forwards to the input's change notification API).
This would mean we would only need to accept one type rather than accepting a performance plus a curve everywhere, and consumers could chain performances and curves however they wanted. It would also mean you could have a "performance" that was slaved to another kind of input than a ticker.