Repository navigation
Description
Problem
When shrinkWrap is used for scrolling widgets, developers are often unaware of what it actually means, a loss of performance due to the entire contents of the scrollable being evaluated.
We have been working on bettering the experience here through the Scroll Performance Pitfalls Project for example:
- Don't use shrink wrap in our samples #116237
- Refactor refresh_indicator.1.dart to not use shrinkwrap #129377
- refactor(news_blocks_ui): remove shrinkwrap VGVentures/news_toolkit#746
- refactor: remove shrinkWrap instances in ListViews VGVentures/news_toolkit#739
- Update Material 3 Demo App samples#1530
- Remove shrinkWrap from samples that don't need it #116236
- Stop recommending "shrinkWrap" #104008
There are a handful of times when shrinkWrap is appropriate, but most of the time users do not need to use it and cost themselves performance issues. It is very easy to just toggle the shrinkWrap flag, and either forget to come back and toggle it off (often the case when fleshing out the UI and the user gets the unbounded error) or revisit it to refactor for efficient scrolling. In some cases, it can be very difficult to refactor if additional UI has been built around the shrinkWrapped viewport (see the news toolkit PRs above). The internet is also working against us here, as there are multiple instances of shrinkWrap on StackOverflow and elsewhere as a recommended solution.
Proposal
For these reasons, we believe shrinkWrap should be deprecated and replaced with an API that is much less obscure as far as what decision the user is making.
For example:
// Old API
ListView(
shrinkWrap: true, // This would be deprecated and ultimately removed
children: myChildrenList,
);
// New API
NonLazyListView(
children: myChildrenList,
);
// * Name subject to better minds' ideas :)This code could be relatively simple, since ListView, GridView and CustomScrollView are already subclasses of ScrollView, the new classes for these could just explicitly set the shrinkWrap property of the super class rather than exposing it as a constructor parameter.
Communication & Migration
The biggest effort here will be communication and migration. There should be 4 main cases:
-
In about half of the cases I have found, shrinkWrap can actually be removed. This often happens when an unbounded error is thrown, the user sets the flag, but then later the scroll view ends up being constrained and the flag is no longer necessary.
-
The developer should refactor just wrapping an Expanded widget around the ScrollView widget. This is commonly seen when a ListView (or other) is placed inside of a Column.
-
The developer should refactor to use a CustomScrollView & slivers instead of ListView (or other).
a. Update some of our ListView samples with CustomScrollViews website#8435 - Refactoring away from shrinkWrap via the CustomScrollView option will be easier if we have more examples of CustomScrollView for our developers
b. Add library of slivers to the website website#8433 -
The developer should refactor to use a SingleChildScrollView if there is only one or very few children, it (basically) operates the same way as shrinkWrap.
-
If it is a safe and relevant use of shrinkWrap, the developer can just switch to the new shrinkWrapping class by renaming the scrolling widget that they used to set
shrinkWrap: trueon.
a. example:ListView -> NonLazyListView
We should tackle this as a whole covering all of these cases:
Affected Classes
- ScrollView
- unsure if this one as the super class should remain, based on comments above
- ListView
- GridView
- CustomScrollView
- ReorderableListView
- AnimatedList
- ReorderableList
- BoxScrollView
Primary Tasks
- Identify remaining shrinkWrap cases in the framework - refactor if possible
- Create design doc that goes into more detail on the new classes, migration plan, and everything covered here
- Add new classes (whatever they may be called)
- Migrate any remaining shrinkWrap in framework, or in use by customers to the new classes
- Deprecate shrinkWrap in all scrolling widgets - referring to new classes
- Document:
- best practices on website
- samples for migration via each path above
- migration guide on website : https://docs.flutter.dev/release/breaking-changes
- flutter-announce
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsTodo
Activity
Piinks commentedon Jul 12, 2023
FYI: I added a fifth scenario above for developers to refactor away from shrinkwrap.
omartinma commentedon Aug 30, 2023
@Piinks Do we have an estimation of when you think this change will be effective? Thanks!
erlangparasu commentedon Oct 14, 2023
Any other widget properties that performance trade-off other than
shrinkWrap?YoussefLasheen commentedon Dec 26, 2023
I was just having a problem with scrolling performance today and it took me like 2 hours to figure out that the shrinkwrap flag was the cause by trial and error. So good work.
flutter-triage-bot commentedon Jan 18, 2024
This issue is marked P1 but has had no recent status updates.
The P1 label indicates high-priority issues that are at the top of the work list. This is the highest priority level a bug can have if it isn't affecting a top-tier customer or breaking the build. Bugs marked P1 are generally actively being worked on unless the assignee is dealing with a P0 bug (or another P1 bug). Issues at this level should be resolved in a matter of months and should have monthly updates on GitHub.
Please consider where this bug really falls in our current priorities, and label it or assign it accordingly. This allows people to have a clearer picture of what work is actually planned. Thanks!
anggaaryas commentedon Jun 19, 2024
Our team use custom scroll view and sliver widget to archive similar behavior with shrink wrap. But it too verbose to use it. Curious how other framework handle this behavior (ex, compose, react, etc)