флаттер разделяет состояние между несколькими экземплярами виджета

В моем приложении 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виджет присутствует и уникален в дереве виджетов.

Надеюсь, это поможет!

Другие вопросы по тегам