Избегайте восстановления дочерних элементов при прокрутке в SliverGrid во флаттере
Привет, я использую приведенный ниже код в CustomScrollView для отображения изображений в сетке с использованием SliverGrid и SliverChildBuilderDelegate. При очень быстрой прокрутке дочерний виджет, который уже имеет кэшированное изображение, уничтожается при выходе за пределы экрана и восстанавливается, когда они находятся на экране. Как избежать их разрушения и восстановления на свитке?
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,
),
)
Примечание: если я удаляю индекс в URL-адресе изображения, то при быстрой прокрутке он загружается очень быстро, поскольку отображает то же изображение.
https://source.unsplash.com/{150}$ / {150 + index}/
3 ответа
Не знаю, нашли ли вы ответ, но у меня сработали эти два варианта: cacheExtent, shrinkWrap false. Вы можете сделать cacheExtent более-менее. Я уверен, что если это слишком много, это потребляет слишком много памяти, поскольку построитель списков управляет памятью за вас, когда он создает и уничтожает.
CustomScrollView(
cacheExtent: 3500,
shrinkWrap: false,
controller: _scrollController,
slivers: <Widget>[
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 1.5,
crossAxisSpacing: 1.5,
childAspectRatio: 0.7,
),
Используйте концепцию класса Wrapper. Это долгое решение. Но вы можете настроить его под свои нужды, чтобы сделать его короче.
Widget decorationImage() {
return DecorationImage(
fit: BoxFit.fill,
image: CachedNetworkImageProvider(
"https://source.unsplash.com/${150}/${150 + index}/",
);
}
Класс Wrapper
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,
),
);
}
}
Используйте этот класс в своем коде как
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());
}
}
Вы можете сбросить эту глобальную конфигурацию
PaintingBinding.instance?.imageCache?.maximumSize = 5000;
PaintingBinding.instance?.imageCache?.maximumSizeBytes = 300 << 20;