-
Notifications
You must be signed in to change notification settings - Fork 29.7k
AlignTransition / DecoratedBoxTransition without rebuilds
#159757
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
|
Is there any benefit to using a final animation rather than allowing users to swap out animations? I feel that could lead to some confusion. |
|
@davidhicks980 good question! Since I personally have never wanted to swap out a transition widget's animation, I made it But I agree that there's a potential for confusion, and with that in mind it might be best to keep it flexible. |
|
@nate-thegrate that makes sense! I was trying to figure out if there was a performance benefit, but code simplicity is not insignificant. |
|
Ooh, speaking of code simplicity—since a bunch of transitions are being defined in the same library, a private mixin could work pretty well. class _RenderAnimatedAlign extends RenderPositionedBox with _RenderTransition {
// ...
}Might end up being even more concise than the code with a |
be6430a to
c3e72b4
Compare
|
Good idea. I almost wonder whether a generic is even needed since the mixin isn't using the value and the _listenable is abstract. In code: mixin _RenderTransition on RenderBox {
Listenable get listenable => _listenable;
abstract Listenable _listenable;
set listenable(Listenable value) {
if (value == _listenable) {
return;
}
_listenable.removeListener(onListenableUpdate);
_listenable = value;
if (attached) {
value.addListener(onListenableUpdate..call());
}
}
// I changed the name of this method to be a little more specific -- not sure if that's a good idea.
void onListenableUpdate();
@override
void attach(PipelineOwner owner) {
super.attach(owner);
_listenable.addListener(onListenableUpdate);
}
@override
void detach() {
_listenable.removeListener(onListenableUpdate);
super.detach();
}
}Though there could be some benefits to typing the mixin. Either way, good idea! |
|
Thanks! Yeah, maybe the method should be renamed (though probably to I tried removing the type argument, and it almost worked: …and then just for kicks, I decided to see if class _RenderAnimatedAlign extends RenderPositionedBox with _RenderTransition {
// ...
@override
covariant ValueListenable<AlignmentGeometry> _listenable;
}and it worked! I'm slightly leaning toward keeping the type argument: if at some point we make But I've never used that keyword on a member variable before; learned something new today! |
c3e72b4 to
c32763b
Compare
c32763b to
b6ba009
Compare
| Widget? child, | ||
| ); | ||
|
|
||
| mixin _RenderTransition<L extends Listenable> on RenderObject { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this private mixin has only one use: Why not inline this logic into the only place where it is used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the way you think 😏
Perhaps you'd be interested in sharing this opinion over at #158255 (comment), since there's a private class that's used in 1 place, unnecessarily increasing the size of the element tree.
My intent was for this mixin to be used for each "transition" widget that simply passes the params to a RO widget.
I can go ahead and use this mixin in a few other places, or I'm also happy to save that for a future PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe do at least one more in this PR to justify the existence of this mixin and also to proof that the abstraction works for other cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good! This PR is now set up for both AlignTransition and DecoratedBoxTransition.
0144d95 to
bfa2834
Compare
AlignTransition without rebuildsAlignTransition / DecoratedBoxTransition without rebuilds
bfa2834 to
1a85357
Compare
goderbauer
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
1a85357 to
4641c29
Compare
|
I guess the good news is: we won't be needing to go through those Google Testing failures! |

This PR reworks the AlignTransition widget to enable skipping the "build" stage of the pipeline entirely.
Additionally, the alignment parameter's type has been changed from
AnimationtoValueListenable, to allow using a ValueNotifier if desired.I ran a benchmark with some colored boxes to see the performance difference between rebuilding each frame vs. updating the render object directly.
Avoiding rebuilds gives a decent boost in profile mode and a significant improvement in debug mode.
I remember there being some concerns about adding a bunch of new RenderObject subclasses, but this one is short enough that I can copy-paste here:
Obviously, a real-world app is going to have a bit more going on than a few "transition" widgets, but still—30 lines of code for a 30% performance boost is a pretty sweet deal!