Reputation: 1079
Hi I am using the below code in a CustomScrollView to show images in grid using SliverGrid and SliverChildBuilderDelegate. On Scrolling very fast, the children widget that has already have cached image gets destroyed when gone off screen and rebuilt when they are on screen. How to avoid them destroying and rebuilding them on scroll?
SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 150,
childAspectRatio: 1 / 1,
crossAxisSpacing: 4.0,
mainAxisSpacing: 4.0,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: Container(
alignment: Alignment.bottomRight,
padding: EdgeInsets.all(10.0),
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.fill,
image: CachedNetworkImageProvider(
"https://source.unsplash.com/${150}/${150 + index}/",
),
),
),
child: index == (index / 2) + 1
? Icon(
Icons.burst_mode,
color: AppTheme.fullWhite,
)
: index == (index / 6)
? Icon(
Icons.play_circle_filled,
color: AppTheme.fullWhite,
)
: Container(),
));
},
childCount: childCount,
),
)
Note: if I remove the index in the image url, then on fast scroll it loads very quickly since its displaying the same image.
https://source.unsplash.com/${150}/${150 + index}/
Upvotes: 1
Views: 2383
Reputation: 1
You can reset this global config
PaintingBinding.instance?.imageCache?.maximumSize = 5000;
PaintingBinding.instance?.imageCache?.maximumSizeBytes = 300 << 20;
Upvotes: 0
Reputation: 1215
Use the Wrapper Class Concept. This is a lengthy solution. But you can customize to your need to make it shorter.
Widget decorationImage() {
return DecorationImage(
fit: BoxFit.fill,
image: CachedNetworkImageProvider(
"https://source.unsplash.com/${150}/${150 + index}/",
);
}
Wrapper class:
class CustomSliverGrid extends StatelessWidget {
Widget _widget;
CustomSliverGrid(this._widget);
@override
Widget build(BuildContext context) {
return SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 150,
childAspectRatio: 1 / 1,
crossAxisSpacing: 4.0,
mainAxisSpacing: 4.0,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: Container(
alignment: Alignment.bottomRight,
padding: EdgeInsets.all(10.0),
decoration: BoxDecoration(
image: _widget,
),
child: index == (index / 2) + 1
? Icon(
Icons.burst_mode,
color: AppTheme.fullWhite,
)
: index == (index / 6)
? Icon(
Icons.play_circle_filled,
color: AppTheme.fullWhite,
)
: Container(),
));
},
childCount: childCount,
),
);
}
}
Use that class in your code as:
class YourWidgetPlace extends StatelessWidget {
Widget decorationImage() {
return DecorationImage(
fit: BoxFit.fill,
image: CachedNetworkImageProvider(
"https://source.unsplash.com/${150}/${150 + index}/",
);
}
@override
Widget build(BuildContext context) {
return CustomSliverGrid(decorationImage());
}
}
Upvotes: 1
Reputation: 671
I don't know if you found an answer, but these two options worked for me: cacheExtent, shrinkWrap false. You can make the cacheExtent more or less. I'm sure if it's too much it consumes too much memory as list builder manages the memory for you as it builds and destroys.
CustomScrollView(
cacheExtent: 3500,
shrinkWrap: false,
controller: _scrollController,
slivers: <Widget>[
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 1.5,
crossAxisSpacing: 1.5,
childAspectRatio: 0.7,
),
Upvotes: 3