Есть ли способ заставить Flutter перерисовать все виджеты (например, после изменения локали)?
Force 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(), каждый раз, когда вызывается этот метод, виджет перерисовывается.
Ответ 3
Что может работать в вашем случае использования, используйте Navigator для перезагрузки страницы. Я делаю это при переключении между "реальным" и "демо" в моем приложении. Вот пример:
Navigator.of(context).push(
new MaterialPageRoute(
builder: (BuildContext context){
return new SplashPage();
}
)
);
Вы можете заменить "новый SplashPage()" в приведенном выше коде любым основным виджетами (или экраном), которые вы хотите перезагрузить. Этот код можно вызывать из любого места, где у вас есть доступ к BuildContext (который является большинством мест в пользовательском интерфейсе).
Ответ 4
Я объясняю, как создать собственный виджет AppBuilder в этом посте.
Вы можете использовать виджет, обернув его своим MaterialApp, например:
Widget build(BuildContext context) {
return AppBuilder(builder: (context) {
return MaterialApp(
...
);
});
}
Вы можете сказать приложение, чтобы восстановить, используя:
AppBuilder.of(context).rebuild();