Slivers in Flutter help build scrollable areas efficiently by creating only visible parts of the UI. This means your app can maintain smooth 60fps scrolling even with large lists or grids. Using SliverList or SliverGrid reduces memory use because off-screen items are not built until needed. The SliverAppBar can expand and collapse smoothly without blocking the main thread, helping keep animations fluid and battery-friendly.
Slivers (SliverList, SliverGrid, SliverAppBar) in Flutter - Build, Publish & Deploy
To keep 60fps with slivers, avoid heavy widgets inside list or grid items. Use const widgets where possible to reduce rebuilds. Use SliverChildBuilderDelegate for lazy building of list/grid items instead of building all at once. Keep the SliverAppBar simple and avoid complex animations inside it. Profile your app with Flutter DevTools to spot jank and optimize expensive builds.
Using slivers does not significantly increase your app bundle size because they are part of Flutter's core widgets. However, complex item widgets inside slivers can increase size if they include many assets or dependencies. Startup time is mostly unaffected by slivers themselves but can be impacted if you preload large data sets for the lists or grids. Lazy loading with slivers helps keep initial load fast.
Flutter slivers behave consistently on iOS and Android because Flutter renders UI itself. However, platform differences appear in scrolling physics: iOS uses bouncing scroll behavior, Android uses edge glow. SliverAppBar respects these platform scroll behaviors automatically. Performance is similar on both platforms, but testing on real devices is recommended to catch platform-specific frame drops.
Both Apple App Store and Google Play require smooth, responsive UI without crashes or freezes. Using slivers helps meet these guidelines by enabling efficient scrolling and reducing memory use. Ensure your app handles accessibility well, including proper labels and focus order in scrollable areas. Avoid excessive memory use in large lists to prevent app termination by the OS. Follow platform-specific UI guidelines for navigation and app bars.
If your screen with slivers takes 5 seconds to load, likely causes include building too many widgets at once instead of lazy loading, heavy widgets inside list/grid items, or expensive computations during build. Check if you are using SliverChildListDelegate with many children instead of SliverChildBuilderDelegate. Use Flutter DevTools to profile widget build times and optimize accordingly.
Practice
SliverAppBar in a Flutter app?Solution
Step 1: Understand
SliverAppBarroleSliverAppBaris designed to create headers that can expand and collapse as the user scrolls.Step 2: Compare options with
Only To create a header that can expand, collapse, and stay visible when scrolling describes the expandable and pinned header behavior ofSliverAppBarbehaviorSliverAppBar.Final Answer:
To create a header that can expand, collapse, and stay visible when scrolling -> Option DQuick Check:
SliverAppBar= expandable header [OK]
- Confusing SliverAppBar with fixed AppBar
- Thinking SliverAppBar creates grids or lists
- Assuming SliverAppBar is a footer widget
SliverList inside a CustomScrollView?Solution
Step 1: Recall
SliverListconstructorSliverListrequires adelegateparameter, usuallySliverChildBuilderDelegateorSliverChildListDelegate.Step 2: Check each option's syntax
SliverList(delegate: SliverChildBuilderDelegate((context, index) => Text('Item $index')))correctly usesdelegate: SliverChildBuilderDelegate. Options A, B, and C use invalid parameters or properties.Final Answer:
SliverList(delegate: SliverChildBuilderDelegate((context, index) => Text('Item $index'))) -> Option BQuick Check:
SliverList needs delegate =SliverList(delegate: SliverChildBuilderDelegate((context, index) => Text('Item $index')))[OK]
- Using children instead of delegate
- Using itemBuilder directly on SliverList
- Passing items instead of delegate
CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: 100,
pinned: true,
flexibleSpace: FlexibleSpaceBar(title: Text('Hello')),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text('Item $index')),
childCount: 3,
),
),
],
)Solution
Step 1: Analyze
The app bar is pinned and has a flexible space with title 'Hello', so it stays visible when scrolling.SliverAppBarpropertiesStep 2: Analyze
The list builds 3 items labeled 'Item 0', 'Item 1', and 'Item 2'.SliverListdelegateFinal Answer:
A scrollable view with a pinned app bar titled 'Hello' and 3 list items labeled Item 0 to Item 2 -> Option AQuick Check:
Pinned SliverAppBar + SliverList with 3 items = A scrollable view with a pinned app bar titled 'Hello' and 3 list items labeled Item 0 to Item 2 [OK]
- Thinking pinned means static, not scrollable
- Confusing list items count or labels
- Assuming SliverAppBar cannot be pinned
CustomScrollView(
slivers: [
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
children: List.generate(4, (index) => Container(color: Colors.blue)),
),
],
)Solution
Step 1: Check
SliverGridconstructor requirementsSliverGridrequires adelegateparameter, notchildren.Step 2: Validate other parts
SliverGridDelegateWithFixedCrossAxisCountis valid, andList.generatecan be used inside a delegate.Final Answer:
SliverGrid requires a delegate, not a children parameter -> Option CQuick Check:
SliverGrid needs delegate, not children [OK]
- Using children instead of delegate in SliverGrid
- Confusing SliverGridDelegateWithFixedCrossAxisCount as invalid
- Thinking CustomScrollView disallows SliverGrid
Solution
Step 1: Identify correct widget for scrollable slivers
CustomScrollViewwithsliversparameter is needed to combineSliverAppBar,SliverGrid, andSliverList.Step 2: Check each option's structure
CustomScrollView(slivers: [SliverAppBar(pinned: true, expandedHeight: 200, flexibleSpace: FlexibleSpaceBar(title: Text('Gallery'))), SliverGrid(delegate: SliverChildBuilderDelegate((c, i) => Image.network(urls[i]), childCount: urls.length), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3)), SliverList(delegate: SliverChildBuilderDelegate((c, i) => ListTile(title: Text(items[i])), childCount: items.length))])correctly usesCustomScrollViewwith slivers and proper delegates.ListView(children: [AppBar(title: Text('Gallery')), GridView.count(crossAxisCount: 3, children: images), ListView(children: texts)])uses nested scrollables incorrectly.CustomScrollView(children: [SliverAppBar(), SliverGrid(), SliverList()])useschildreninstead ofslivers.Column(children: [SliverAppBar(), SliverGrid(), SliverList()])usesColumnwhich cannot host slivers.Final Answer:
CustomScrollView with SliverAppBar, SliverGrid, and SliverList using delegates -> Option AQuick Check:
Use CustomScrollView with slivers and delegates =CustomScrollView(slivers: [SliverAppBar(pinned: true, expandedHeight: 200, flexibleSpace: FlexibleSpaceBar(title: Text('Gallery'))), SliverGrid(delegate: SliverChildBuilderDelegate((c, i) => Image.network(urls[i]), childCount: urls.length), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3)), SliverList(delegate: SliverChildBuilderDelegate((c, i) => ListTile(title: Text(items[i])), childCount: items.length))])[OK]
- Using ListView or Column instead of CustomScrollView for slivers
- Passing slivers as children instead of slivers parameter
- Not using delegates for SliverGrid and SliverList
Ready to prove it?
Pass the test and this pattern moves unknown
