Вопрос или проблема
Я использовал Futurebuilder для получения адресов пользователей в showmodalbottomsheet, все работает нормально, но при прокрутке он обновляется и делает ненужные запросы из-за future builder.
Я хочу предотвратить перестройку modalbottom sheet, чтобы он не обновлялся при прокрутке…
Надеюсь, моя точка зрения ясна…
Чтобы объяснить подробнее, я создал этот демонстрационный пример, где цвет меняется при прокрутке
Future<dynamic> showAddressModalBottomSheet(BuildContext context) async
{
return showModalBottomSheet(
context: context, builder: (_){
return Container(
color: Color.fromRGBO(Random().nextInt(255), Random().nextInt(255), Random().nextInt(255), 1),
);
});
}
Ответ или решение
Чтобы предотвратить перезагрузку showModalBottomSheet
в Flutter, особенно когда используется FutureBuilder
, необходимо принимать во внимание несколько ключевых аспектов, которые помогут обеспечить плавность работы интерфейса и минимизировать ненужные вызовы.
1. Используйте StatefulWidget
для управления состоянием
Первое решение, которое можно предложить — это использование StatefulWidget
вместо FutureBuilder
внутри вашего showModalBottomSheet
. Это позволит вам сохранить состояние данных и избежать их повторной загрузки при прокрутке.
class AddressModal extends StatefulWidget {
@override
_AddressModalState createState() => _AddressModalState();
}
class _AddressModalState extends State<AddressModal> {
Future<List<Address>>? _addresses;
@override
void initState() {
super.initState();
_addresses = fetchUserAddresses();
}
@override
Widget build(BuildContext context) {
return FutureBuilder<List<Address>>(
future: _addresses,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Ошибка загрузки адресов'));
}
final addresses = snapshot.data ?? [];
return ListView.builder(
itemCount: addresses.length,
itemBuilder: (context, index) => ListTile(
title: Text(addresses[index].name),
),
);
},
);
}
}
Здесь мы загружаем адреса один раз в методе initState
, и они остаются в памяти, предотвращая повторные запросы при прокрутке.
2. Кэширование данных
Вы также можете рассмотреть возможность кэширования данных, полученных с помощью FutureBuilder
или другого механизма. Храните загруженные адреса в переменной состояния. Если данные уже были загружены, используйте их повторно:
class AddressModal extends StatefulWidget {
@override
_AddressModalState createState() => _AddressModalState();
}
class _AddressModalState extends State<AddressModal> {
List<Address>? _addresses;
Future<void> fetchUserAddresses() async {
// Логика загрузки адресов
_addresses = await fetchAddressesFromApi();
}
@override
void initState() {
super.initState();
fetchUserAddresses();
}
@override
Widget build(BuildContext context) {
return _addresses == null
? Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: _addresses!.length,
itemBuilder: (context, index) => ListTile(
title: Text(_addresses![index].name),
),
);
}
}
3. Использование Provider
или других управлений состоянием
Использование архитектурного паттерна управления состоянием, такого как Provider
, Bloc
или Riverpod
, может значительно упростить работу с состоянием данных. Это поможет избежать ненужных перезагрузок интерфейса:
- Создайте свой класс состояния, который будет загружать адреса.
- Используйте этот класс в
showModalBottomSheet
, чтобы получить данные.
Пример с использованием Provider
:
class AddressProvider with ChangeNotifier {
List<Address>? _addresses;
Future<void> loadAddresses() async {
if (_addresses == null) {
_addresses = await fetchAddressesFromApi();
notifyListeners();
}
}
List<Address>? get addresses => _addresses;
}
// Внутри вашего метода
showModalBottomSheet(context) {
return ChangeNotifierProvider(
create: (_) => AddressProvider()..loadAddresses(),
child: Consumer<AddressProvider>(
builder: (context, provider, child) {
if (provider.addresses == null) {
return Center(child: CircularProgressIndicator());
}
return ListView.builder(
itemCount: provider.addresses!.length,
itemBuilder: (context, index) => ListTile(
title: Text(provider.addresses![index].name),
),
);
},
),
);
}
Заключение
Предотвращение лишней перезагрузки showModalBottomSheet
в Flutter требует применения правильных паттернов управления состоянием. Использование StatefulWidget
, кэширования и управления состоянием с помощью таких решений, как Provider
, позволит вам избежать ненужных запросов и сделать интерфейс более плавным и отзывчивым. Следуя приведённым рекомендациям, вы сможете улучшить пользовательский опыт в вашем приложении.