Когда создаем приложение с вкладками или списками, может возникнуть такая ситуация: пользователь переключается между вкладками, а состояние старой вкладки сбрасывается. Такое может раздражать, особенно если это список, который прокрутили до 155 номера, видео или текст.
Проблема
Допустим, у нас есть 3 вкладки, и каждая из них — это StatefulWidget с вложенными виджетами. Когда мы перелистываем между ними, Flutter по умолчанию «выгружает» неактивную вкладку, чтобы экономить память.
Что происходит:
Проскроллили вниз на 1-й вкладке ➡️ переключились на 2-ю ➡️
вернулись обратно на 1-ю ➡️
все обнулилось — нас кинуло в самое начало.
Решение
AutomaticKeepAliveClientMixin — это миксин, который говорит Flutter: «Пожалуйста, не выгружай меня, даже если я временно не на экране». Он работает вместе с PageStorage — специальным механизмом Flutter для хранения состояний виджетов.
Как использовать
На коленке наклепали такой виджет, который каждый раз будет сбрасывать свое состояние:
class MyTab extends StatefulWidget {
@override
_MyTabState createState() => _MyTabState();
}
class _MyTabState extends State<MyTab> {
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 100,
itemBuilder: (_, index) => ListTile(title: Text('Item $index')),
);
}
}Теперь добавляем AutomaticKeepAliveClientMixin, чтобы этого не происходило:
class _MyTabState extends State<MyTab> with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true; // СУПЕР ВАЖНО
@override
Widget build(BuildContext context) {
super.build(context); // ОБЯЗАТЕЛЬНО ВЫЗЫВАТЬ
return ListView.builder(
itemCount: 100,
itemBuilder: (_, index) => ListTile(title: Text('Item $index')),
);
}
}❕Миксин работает только в тех местах, где Flutter может использовать KeepAlive, например, в TabBarView, PageView, ListView.builder, внутри PageStorage.
Где использовать
▫️Вкладки (TabBarView), чтобы запоминать положение и состояние
▫️Страницы в PageView, например, в onboarding-экранах
▫️Динамические списки, где хотим сохранить scroll-положение и состояние каждого элемента
Как быстро проверить, что KeepAlive работает
Работает, если initState called будет вызван только один раз:
@override
void initState() {
super.initState();
print('initState called');
}
📎Документы по миксину — здесь
🔥 — если использовали AutomaticKeepAliveClientMixin на практике
