Предотвращение повторного рендеринга дерева виджетов Flutter при обновлении магазина мобов и повышении производительности - PullRequest
0 голосов
/ 26 марта 2020

Я пытался создать приложение, используя флаттер, и мне трудно разобраться в некоторых концепциях флаттера. Я надеюсь найти здесь несколько ответов.

Предисловие: Зависимости приложения: flutter_mobx, auto_route, get_it .

Я создаю приложение, в котором мне нужно показать несколько предупреждений. , Я создал страницу флаттера (AlertsScreen), на которую подписано mobx alerts_store . Поэтому всякий раз, когда я пытаюсь выдать sh предупреждение в alerts_store , должна появиться снэк-бар. Нечто похожее на то, что я делал в сети React.

Ссылка на репозиторий приложения: https://github.com/ganeshrvel/open_cloud_encryptor/tree/new-router-logic

Вопросы:

  1. Как это сделать Я монтирую общий виджет типа AlertsScreen(), который будет отображаться в приложении. Раньше я делал что-то вроде этого:

app.dart ( ссылка Github )

MaterialApp(
  builder: (BuildContext context, Widget widget) {
    setErrorBuilder();
    return Column(
      children: <Widget>[
        Expanded(
          child: widget,
        ),
        AlertsScreen(),
      ],
    );
  },
  title: 'App name',
  onGenerateRoute: Router.onGenerateRoute,
  initialRoute: Router.splashScreen,
  navigatorKey: Router.navigator.key,
),

Но потом всякий раз, когда я пытаюсь отрендерить Flushbar или любой другой другой элемент внутри AlertsScreen, для которого требуется context, выдает ошибку:

[ОШИБКА: flutter / lib / ui / ui_dart_state. cc (157)] Необработанное исключение: операция навигатора запрошена с контекстом это не включает в себя навигатор. Контекст, используемый для pu sh или поп-маршрутов из навигатора, должен соответствовать контексту виджета, являющегося потомком виджета навигатора.

Пример кода Flushbar:

Flushbar(title: 'title',message: 'body',duration: const Duration(seconds: 5),).show(context);

Как мне смонтировать общий виджет типа AlertsScreen в приложении и который всегда будет виден для любого вида деятельности?

2) Этот ответ из stackoverflow предлагает создать CommonWidget виджет без состояния и используйте его везде, где он должен быть представлен. Поэтому, принимая подсказки из приведенного выше ответа stackoverflow, я изменил свой код следующим образом:

common_widget.dart ( Github link )

class CommonWidget extends StatelessWidget {
 final Widget child;

const CommonWidget({
    @required this.child,
  });

 @override
  Widget build(BuildContext context) {
 return Column(
      children: <Widget>[
        Expanded(
          child: child,
        ),
        AlertsScreen(),
      ],
    );
  }
}

home.dart ( Github link )

class _HomeScreenState extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Home'),
      ),
      body: CommonWidget(
        child: Center(
          child: Column(),
        ),
      ),
    );
  }
}

Это правильный способ сделать это?

3) Я использую flutter_mobx в качестве хранилища для AlertsScreen. Поскольку я использовал CommonWidget на нескольких экранах для отображения AlertsScreen, при каждом обновлении магазина AlertsScreen перестраивался несколько раз. Как мне это предотвратить? Как сделать так, чтобы виджет AlertsScreen перерисовывался только на текущем экране, и предотвратить его восстановление во всех других местах при обновлении магазина?

Текущий обходной путь выглядит примерно так:

alerts .dart ( Github Link )

@override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _alertsStore ??= Provider.of<AlertsStore>(context);
    _disposers ??= [
      reaction(
        (_) => _alertsStore.alertsList.iterator,
        (alertsList) {
          if (ModalRoute.of(context).isCurrent) { // Check whether current screen is rendered 
            buildSnackbar();
          }
        },
      ),
    ];
  }

Есть ли лучший способ сделать это?

...