флаттер разделяет состояние между несколькими экземплярами виджета
В моем приложении Flutter есть ConnectivityStatus
виджет, который отображает текущий статус подключения приложения к моему Raspberry Pi. вinitState
своего виджета я подписываюсь на таймер, чтобы проверять соединение каждые 5 секунд и соответствующим образом обновлять состояние, а затем отказаться от подписки при удалении.
Проблема в том, что когда на нескольких экранах используется ConnectivityStatus
виджет, например, в настройке навигатора стека, теперь у меня есть две одновременные подписки, поскольку ни один экземпляр не удален. Это вызывает появление множества избыточных, ненужных запросов.
Что я действительно хочу, так это либо поделиться одним экземпляром виджета на нескольких экранах, либо иметь одно глобальное состояние, к которому могут обращаться несколько экземпляров.
Как я могу добиться этого или какие другие рекомендуемые решения моей проблемы?
3 ответа
Самый простой способ добиться этого - использовать InheritedWidget для передачи ConnectivityStatus нисходящим виджетам. https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html
Вы также можете изучить другие решения для управления состоянием, такие как Provider https://pub.dev/packages/provider или Bloc https://pub.dev/packages/flutter_bloc.
Я предлагаю использовать Provider и создать RPIService
который отправляет поток сведений о состоянии подключения.
class RPIService {
var RPIstatus = ValueNotifier<Status>(Status('offline'));
RPIService(){
rpi...listen((cstatus){
RPIstatus.add(Status(cstatus));
});
}}
class Status {
final String statusMessage;
Status(this.statusMessage);
}
main.dart
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider<UserService>(
create: (context) => UserService(),
lazy: false,
),
StreamProvider<Status>(
create: (context) =>
Provider.of<RPIService>(context, listen: false).RPIstatus,
),
],
child: MaterialApp(
title: 'Your app',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: YourHome(),
),
);
}
}
yourHome.dart
class YourHome extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<Status>(builder: (context, status, _) {
return Scaffold(
body: Text(status.status),
);
});
}
}
Другой способ добиться этого - использовать GlobalKey
, поскольку это официальный способ Flutter поделиться одним состоянием виджета в приложении.
В key.dart
файл:
final GlobalKey<ConnectivityStatusState> connectivityStatusKey = GlobalKey();
Когда вы создаете свой ConnectivityStatus
виджет:
ConnectivityStatus(
key: connectivityStatusKey,
...
)
Где вы хотите получить доступ к ConnectivityStatus
штат:
connectivityStatusKey.currentState.anythingPublicInThisState()
Чтобы использовать это, убедитесь, что ваш класс состояния является общедоступным (без _
) и ConnectivityStatus
виджет присутствует и уникален в дереве виджетов.
Надеюсь, это поможет!