Skip to content

Breaking changes that would improve the overall API #24722

Description

@Hixie

This bug lists changes we'll probably never make, but should consider if we ever for some reason decided to start over in a new universe.

Foundation

  • ChangeNotifier and Listenable and company are a bit mixed up. We could refactor the code here so that we more clearly have a Listenable and a ListenableController, and a ValueListenable and a ValueListenableController, and so on.

Services

  • StandardMessageCodec should be a static class or should be stateful.
  • dev.flutter/channel-buffers control messages should use a more efficient binary format rather than an inefficient bespoke \r-delimited text-based format.
  • flutter/system, flutter/navigation, etc, control messages should use a more efficient binary format rather than JSON.

Painting

  • addListener/removeListener on ImageStream have a broken API that should be redesigned.
  • NotchedShape should be a shape, or should have another name.
  • TextStyle has many decoration properties, it would be nice if they were all in one object, maybe separate objects for underline and overline and strike-through.

Gestures

  • Rename PointerMoveEvent to PointerUpdateEvent, because it's also triggered at button changes without moves.

Animation

Rendering

  • Adaptor -> Adapter
  • SliverChildListDelegate should have a children argument instead of a positional one
  • CustomPainter.hitTest should take a Size argument (CustomPainter.hitTest missing size argument #28206)
  • Layer.pushLayer should be renamed to withLayer, since it is not matched by a popLayer. The same applies to its relatives.
  • BlendMode.srcATop -> BlendMode.srcAtop
  • BlendMode.dstATop -> BlendMode.dstAtop

Widgets

  • TabController should be a ValueListenable
  • Rename WidgetBuilder to make it clear it's a typedef.
  • Rename TransitionBuilder to make it clear it's a typedef with a child.
  • Rename AnimatedBuilder to make it clear it takes any Listenable (even AnimationBuilder would be more consistent...), see also: Breaking changes that would improve the overall API #24722 (comment).
  • Rename Listener to be PointerListener
  • (Subclasses of) AnimatedWidget and ImplicitlyAnimatedWidget should be named consistently (see Breaking changes that would improve the overall API #24722 (comment)).
  • Name the Foo vs FooTransition vs AnimatedFoo widgets more consistently (e.g. FadeTransition vs AnimatedOpacity, also AnimatedSize).
  • Consider merging all the one-argument FooBuilder typedefs into one generic typedef, or otherwise cleaning up the inconsistencies there.
  • inheritFromWidgetOfExactType should be generic rather than taking a Type (so it can guarantee its return type is of the same type as the argument).
  • Container's width and height properties should size the child, and imply an alignment.
  • It's weird that we have both showDialog and showGeneralDialog.
  • AnimatedList should be AnimatedListView.
  • SliverMultiBoxAdaptorWidget is not an adaptor; consider naming like SliverMultiChildRenderObjectWidget.
  • Rename RichText to RawText.
  • Change the type of maxLines from int to double (TextField maxLines should be a double, not an int. #35064).
  • ColorFiltered -> ColorFilter
  • Be consistent about callback parameter names for tapping/pressing something (onTap vs onPressed, Be consistent about callback parameter names for tapping/pressing something #17407)
  • FocusNode and FocusScopeNode should use 'focusable' instead of 'canRequestFocus' as the attribute for controlling focusability.
  • MediaQueryData.disableAnimations should be called MediaQueryData.enableAnimations with the opposite semantics (see style guide under "double negatives").
  • MediaQuery.viewPadding should be used instead of MediaQuery.padding throughout the framework. viewPadding was added ATF to address edge cases, but the API surface has become confusing as a result, see SafeArea.maintainBottomViewPadding should be true by default #59204
  • Element.activate should rename to Element.reactivate, because only the reactivate will callback.
  • OnInvokeCallback should be called just InvokeCallback per the style guide.
  • Navigator: reportsRouteUpdateToEngine should be reportRouteUpdateToEngine (imperative not descriptive).
  • Better property's naming for Form widget (autoValidateMode, instead of autovalidateMode) #115820

Material

  • ColorScheme.on* shouldn't look like event handlers
  • Handle the tap target padding for e.g. mini fabs more intuitively (dunno what that would entail exactly)
  • InputDecoration.filled should be isFilled
  • InputDecoration should only have one prefix field and one suffix field, rather than three each (widget, icon, text). And it probably should have an error, a label, and a hint instead of just errorText, labelText, and hintText.
  • Change Divider and VerticalDivider's indent and endIndent properties to simply be margin
  • Colors.grey -> Colors.gray

Activity

  1. added
    frameworkflutter/packages/flutter repository. See also f: labels.
    c: API breakBackwards-incompatible API changes
    on Nov 26, 2018
  2. added this to the milestone on Nov 26, 2018
  3. SteveAlexander commented on Nov 27, 2018

    @SteveAlexander

    May I propose this for the Framework too? #19143

    I currently have some pretty ugly code to allow me to sequence an animation of changing tab and then scrolling to a certain position. This is because while ScrollController.animateTo returns a Future so I can sequence something to happen after scrolling is done, TabController.animateTo is void.

    Workaround (in the referenced issue above) is complicated and slightly absurd :-)

  4. Hixie commented on Nov 27, 2018

    @Hixie
    ContributorAuthor

    We should just be able to fix #19143, turning something from returning void to returning a Future when it's something that we don't expect people to implement shouldn't be a breaking change.

    This bug is specifically about changes we can never really make because they're breaking changes.

  5. jonahwilliams commented on Jan 11, 2019

    @jonahwilliams
    Contributor

    Adding a type parameter to invokeMethod would be nice too: #17333

    Done, and non-breaking

  6. jamesderlin commented on Mar 29, 2019

    @jamesderlin
    Contributor

    May I complain here that I dislike how Stack expects its children ordered back-to-front in z-order? For example:

    Stack(children: [
      child1,
      child2,
      child3,
    ])
    

    I find it rather unintuitive that child1 appears on top in the code but is actually at the bottom of the stack.

  7. rrousselGit commented on May 20, 2019

    @rrousselGit
    Contributor

    Just passing there after listening to your awesome podcast on itsallwidgets.com

    ChangeNotifier and Listenable and company are a bit mixed up. We could refactor the code here so that we more clearly have a Listenable and a ListenableController, and a ValueListenable and a ValueListenableController, and so on.

    What does it mean? Moving toward an API closer to Stream vs StreamController for Listenable?

    Container's width and height properties should size the child, and imply an alignment.

    I'm not sure I agree with that one.
    While the current behavior is definitely surprising for newcomers, that's a good thing IMO.

    From my experience mentoring in Flutter, that specific API is usually the first step that led peoples understanding that Flutter does layout differently.
    This helped my mentees a lot in understanding that, in Flutter, UI elements means nothing without the rest of the tree – and that everything is declarative to the core.

  8. goderbauer commented on Aug 1, 2019

    @goderbauer
    Member

    AnimatedWidget, ImplicitlyAnimatedWidget and their subclasses should be named consistently. For the most part, subclasses of AnimatedWidget are named FooTransition and subclasses of of ImplicitlyAnimatedWidget are named AnimatedFoo. There are annoying/unnecessary exceptions, though, which should be renamed for consistency:

    • AnimatedModalBarrier (subclass of AnimatedWidget) should be renamed to ModalBarrierTransition
    • AnimatedBuilder (subclass of AnimatedWidget) should be renamed to something like TransitionBuilder *)
    • AnimatedWidget itself should probably more accurately be named TransitionWidget
    • Maybe: ImplicitlyAnimatedWidget should just be AnimatedWidget
    • Name the Foo vs FooTransition vs AnimatedFoo widgets more consistently (e.g. Opacity vs FadeTransition vs AnimatedOpacity).

    *) This would also fix another item on the list above: "Rename AnimatedBuilder to make it clear it takes any Listenable (even AnimationBuilder would be more consistent...)."

  9. Hixie commented on Aug 1, 2019

    @Hixie
    ContributorAuthor

    Please feel free to edit the list above so that we just have one comment with all the proposed changes.

  10. goderbauer commented on Aug 2, 2019

    @goderbauer
    Member

    @Hixie I added a bullet to the list in the top post and linked to the detailed description in the comments.

  11. efortuna commented on Sep 22, 2019

    @efortuna
    Contributor

    @goderbauer is the animations group planning on renaming some of these like you mentioned (such as AnimatedModalBarrier)?

    One other to add to the list of naming mismatches is AnimatedSize.

  12. goderbauer commented on Sep 23, 2019

    @goderbauer
    Member

    I added AnimatedSize to the list above.

    I did not have plans to rename these. It feels like the change would be rather disruptive to current users of these without any benefit for them?

  13. tvolkert commented on Dec 4, 2019

    @tvolkert
    Contributor

    When we look to do a Flutter 2.0 release, we should consider doing the things listed in this issue as part of the 1.x->2.x break.

  14. 21 remaining items

  15. added
    P3Issues that are less important to the Flutter project
    and removed on Jun 28, 2023
  16. bartekpacia commented on May 1, 2024

    @bartekpacia
    Member

    It seems to me that some naming-related items on this list could be done by renaming the offending identifiers, and introducing a temporary (for ~1 year/4 major releases) type-alias with the old name.

    For example:

    • Adapter -> Adaptor
    • BlendMode.srcATop -> BlendMode.srcAtop
    • BlendMode.dstATop -> BlendMode.dstAtop
  17. Piinks commented on Jul 18, 2024

    @Piinks
    Contributor

    Adding this one as well: #61690

  18. nate-thegrate commented on Aug 14, 2024

    @nate-thegrate
    Contributor

    Some things I felt like adding here:


    • Convert Builder classes into constructors and make the builder argument positional

    Builder and StatefulBuilder can be useful, but there's no benefit to extending those classes; instead they could be Widget.builder and Widget.statefulBuilder.

    // before
    child: Builder(builder: (context) {
      return FooWidget();
    })
    
    // after
    child: .builder((context) {
      return FooWidget();
    })

    Freeing up the namespace would be beneficial, e.g. a developer (or this framework) could use Builder as a class or typedef without a name overlap.


    • Combine Animatable<T> and ParametricCurve<T>

    Animatable has a transform method which creates a value based on a double t parameter (a fraction in the range 0.0 to 1.0); ParametricCurve.transform() does pretty much exactly the same thing.
    But a few differences in the implementation make it so we can't just have one of those classes as a subtype of the other without breakages.


    • Get rid of PreferredSizeWidget

    Any logic that needs the dimensions of one or more children should handle it during RenderObject.performLayout.


    • Rework AutomaticKeepAliveClientMixin

    Instructing developers to call super.build(context) and ignore the return value is unintuitive API design IMO. I'd prefer one of the following:

    • Introduce a public method that returns void instead of overriding build
    • Make it a mixin on StatefulWidget: you'd override the wantKeepAlive getter on the widget class, and the mixin would change createElement so that no changes to the state's build method are needed.

    • Separate packages for framework layers it came true! 🙂
  19. justinmc commented on Nov 20, 2024

    @justinmc
    Contributor

    A small one: SelectionChangedCause.scribble should be renamed to SelectionChangedCause.stylusHandwriting to indicate that it is not iOS-specific.

    Tracked in: #159223

  20. colbymaloy commented on Nov 27, 2024

    @colbymaloy

    could you please add some gesture information to the hitTest method for custompainter??? for example when using interactiveViewer and painting a list of items, say like a map with points of interest, i need to detect taps on those items.

    hitTest gets triggered when panning on the map, causing accidental clicks. if hitTest has some info about which gesture happened i could make it work. Current workaround is to wrap CustomPaint in a GestureDetector and use onTapDown.

  21. feinstein commented on Nov 27, 2024

    @feinstein
    Contributor

    I think you might be using hitTest wrongly. It's purpose is not to tell you that your widget was tapped, so you can call a callback, or trigger some logic. It's purpose is for you to inform the framework that there's something in those coordinates, so the gesture detection algorithm can decide which widget is being tapped (as you might be tapping on a transparent area in your widget, so the widget that's behind can get that gesture instead), and will get the gesture callback activated.

  22. caseycrogers commented on Mar 19, 2025

    @caseycrogers
    Contributor

    Developers often use ValueChanged<T> in contexts where the function isn't being called on changes and has nothing to do with changing values-they just wanted a type def for void Function(T) and ValueChanged was handy.

    As such, ValueChanged<T> should've just been called ValueCallback<T> to make it more obviously usable outside of strictly on change callbacks.

  23. mateusfccp commented on Mar 19, 2025

    @mateusfccp
    Contributor

    Developers often use ValueChanged<T> in contexts where the function isn't being called on changes and has nothing to do with changing values-they just wanted a type def for void Function(T) and ValueChanged was handy.

    As such, ValueChanged<T> should've just been called ValueCallback<T> to make it more obviously usable outside of strictly on change callbacks.

    This can be no breaking. If found valuable, we can introduce one without removing the other. They would be virtually equal, but have different semantics.

  24. feinstein commented on Mar 19, 2025

    @feinstein
    Contributor

    I agree this would be a nice addition, in the mean time remember that the framework also provides ValueSetter<T>.

  25. ValentinVignal commented on Jul 1, 2026

    @ValentinVignal
    Contributor

    Another one: #187909

    WidgetController from packages/flutter_test/lib/src/controller.dart should not be using a static variable _nextPointer as a counter. It is making the tests dependent on each other in some specific scenarios.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Issues that are less important to the Flutter projectc: API breakBackwards-incompatible API changesframeworkflutter/packages/flutter repository. See also f: labels.team-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions