Force Flutter перерисовать все виджеты

Есть ли способ заставить Flutter перерисовать все виджеты (например, после изменения локали)?

Ответ 1

Этот тип прецедента, где у вас есть данные, которые могут читать дети, но вы не хотите явно передавать данные в аргументы конструктора всех ваших детей, обычно вызывает InheritedWidget. Flutter будет автоматически отслеживать, какие виджеты зависят от данных и перестроить измененные части вашего дерева. Существует виджет LocaleQuery, который предназначен для обработки изменений локали, и вы можете видеть, как он используется в Пример приложения с запасами.

Вкратце, вот что делает Stocks:

  • Поместите обратный вызов корневого виджета (в данном случае, StocksApp) для обработки изменений локали. Этот обратный вызов выполняет некоторую работу, а затем возвращает настраиваемый экземпляр LocaleQueryData
  • Зарегистрировать этот обратный вызов как аргумент onLocaleChanged конструктору MaterialApp
  • В дочерних виджетах, которым нужна информация о локали, используйте LocaleQuery.of(context).
  • При изменении локали, Flutter только перерисовывает виджеты, которые имеют зависимости от данных локали.

Если вы хотите отслеживать что-то другое, кроме изменений локали, вы можете создать свой собственный класс, который расширяет InheritedWidget и включает его в иерархии рядом с корнем вашего приложения. Его родительский элемент должен быть StatefulWidget с ключом, установленным в GlobalKey, доступным для детей. State StatefulWidget должен владеть данными, которые вы хотите распространять и выставлять методы для их изменения, которые вызывают setState. Если дочерние виджеты хотят изменить данные State, они могут использовать глобальный ключ, чтобы получить указатель на State (key.currentState) и вызвать методы на нем. Если они хотят прочитать данные, они могут вызвать статический метод of(context) вашего подкласса InheritedWidget, и это скажет Flutter, что эти виджеты необходимо перестраивать, когда ваш State вызывает setState.

Ответ 2

У вашего виджета должен быть метод setState(), каждый раз, когда вызывается этот метод, виджет перерисовывается.

Документация: Виджет setState()

Ответ 3

Что может работать в вашем случае использования, используйте Navigator для перезагрузки страницы. Я делаю это при переключении между "реальным" и "демо" в моем приложении. Вот пример:

Navigator.of(context).push(
    new MaterialPageRoute(
        builder: (BuildContext context){
          return new SplashPage();
        }
    )
);

Вы можете заменить "новый SplashPage()" в приведенном выше коде любым основным виджетами (или экраном), которые вы хотите перезагрузить. Этот код можно вызывать из любого места, где у вас есть доступ к BuildContext (который является большинством мест в пользовательском интерфейсе).

Ответ 4

Я объясняю, как создать собственный виджет AppBuilder в этом посте.

https://hillelcoren.com/2018/08/15/flutter-how-to-rebuild-the-entire-app-to-change-the-theme-or-locale/

Вы можете использовать виджет, обернув его своим MaterialApp, например:

Widget build(BuildContext context) {
  return AppBuilder(builder: (context) {
    return MaterialApp(
      ...
    );
  });
}

Вы можете сказать приложение, чтобы восстановить, используя:

AppBuilder.of(context).rebuild();