有没有办法强制Flutter重绘所有小部件(例如在区域设置更改后)?
答案 0 :(得分:15)
这种类型的用例,你有孩子可以阅读的数据,但你不想将数据显式传递给你所有孩子的构造函数参数,通常需要InheritedWidget
。 Flutter将自动跟踪哪些小部件依赖于数据并重建已更改的树的部分。有LocaleQuery
窗口小部件用于处理区域设置更改,您可以在Stocks example app中看到它的使用方式。
简而言之,这就是Stocks正在做的事情:
StocksApp
)进行回调以处理区域设置更改。此回调执行一些操作,然后返回LocaleQueryData
onLocaleChanged
构造函数MaterialApp
参数
LocaleQuery.of(context)
。如果要跟踪区域设置更改以外的其他内容,可以创建自己的扩展InheritedWidget
的类,并将其包含在应用根目录附近的层次结构中。其父级应为StatefulWidget
,其密钥设置为GlobalKey
,可供儿童访问。 State
的{{1}}应该拥有您要分发的数据,并公开更改调用StatefulWidget
的方法。如果子窗口小部件想要更改setState
的数据,他们可以使用全局键来获取指向State
(State
)的指针并在其上调用方法。如果他们想要读取数据,他们可以调用key.currentState
子类的静态of(context)
方法,这将告诉Flutter这些小部件需要在InheritedWidget
调用{{1}时重建}}
答案 1 :(得分:10)
刷新整个小部件树可能会很昂贵,并且当您在用户面前看到它时,看起来似乎并不甜美。
为此,颤振具有ValueListenableBuilder<T> class
。它仅允许您重建一些您所需的小部件,而跳过昂贵的小部件。
您可以在此处查看文档ValueListenableBuilder flutter docs
或下面的示例代码:
return Scaffold(
appBar: AppBar(
title: Text(widget.title)
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('You have pushed the button this many times:'),
ValueListenableBuilder(
builder: (BuildContext context, int value, Widget child) {
// This builder will only get called when the _counter
// is updated.
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('$value'),
child,
],
);
},
valueListenable: _counter,
// The child parameter is most helpful if the child is
// expensive to build and does not depend on the value from
// the notifier.
child: goodJob,
)
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.plus_one),
onPressed: () => _counter.value += 1,
),
);
而且永远不要忘记 setState(() {});
答案 2 :(得分:5)
简单使用:
Navigator.popAndPushNamed(context,'/screenname');
每当您需要刷新时:)
答案 3 :(得分:4)
您的Widget应该有一个setState()方法,每次调用此方法时,都会重绘窗口小部件。
答案 4 :(得分:3)
在这篇文章中,我将解释如何创建自定义的“ AppBuilder”小部件。
您可以通过将其与MaterialApp一起包装来使用该小部件,例如:
Widget build(BuildContext context) {
return AppBuilder(builder: (context) {
return MaterialApp(
...
);
});
}
您可以使用以下方法告诉应用重建:
AppBuilder.of(context).rebuild();
答案 5 :(得分:2)
老问题,但这是解决方案:
在您的build
方法中,调用rebuildAllChildren
函数并将其传递给context
:
@override
Widget build(BuildContext context) {
rebuildAllChildren(context);
return ...
}
void rebuildAllChildren(BuildContext context) {
void rebuild(Element el) {
el.markNeedsBuild();
el.visitChildren(rebuild);
}
(context as Element).visitChildren(rebuild);
}
这将拜访所有孩子并将他们标记为需要重建。 如果将此代码放在窗口小部件树中最顶层的窗口小部件中,它将重建所有内容。
还请注意,您必须订购该特定小部件才能进行重建。另外,您可以使用一些布尔值,以便仅在您真正需要它时才重建该小部件的所有子部件(当然,这是一项昂贵的操作)。
重要提示::这是一个hack,只有在知道自己在做什么并且有充分理由这样做时,才应该这样做。我的国际化软件包中有一个示例,其中有此必要:https://pub.dev/packages/i18n_extension。正如科林·杰克逊(Collin Jackson)在回答中解释的那样,您实际上一般不应该这样做。
答案 6 :(得分:1)
对您的用例可能有用的是使用Navigator重新加载页面。我在&#34;真实&#34;之间切换时这样做和&#34;演示&#34;在我的应用程序模式。这是一个例子:
Navigator.of(context).push(
new MaterialPageRoute(
builder: (BuildContext context){
return new SplashPage();
}
)
);
您可以替换&#34;新的SplashPage()&#34;在上面的代码中,您想要重新加载任何主要小部件(或屏幕)。可以从有权访问BuildContext的任何地方调用此代码(这是UI中的大多数位置)。
答案 7 :(得分:1)
还有一个名为states_rebuilder的发布包可以解决这个问题。
答案 8 :(得分:0)
如果要创建多语言应用程序,建议您使用本地化库来处理。甚至使用其他应用程序使用的约定。
flutter_i18n-它还具有一种在运行时重新生成的方法-记录在底部
await FlutterI18n.refresh(buildContext, languageCode, {countryCode});
它的作用是生成状态的小部件,这些状态由处理动态数据和可见性的组合singelton资源管理。
答案 9 :(得分:-1)
使用 AppBuilder 小部件制作重绘小部件
<div class="container">
<a href="" style="border: solid">Item</a>
<a href="" style="border: solid">Item</a>
<a href="" style="border: solid">Item</a>
<a href="" style="border: solid">Item</a>
</div>
答案 10 :(得分:-1)
简单使用:
Navigator.popAndPushNamed(context,'/xxx');