Force Flutter to redraw all widgets

2019-01-27 16:21发布

问题:

Is there a way to force Flutter to redraw all widgets (e.g. after locale change)?

回答1:

This type of use case, where you have data that children can read but you don't want to explicitly pass the data to the constructor arguments of all your children, usually calls for an InheritedWidget. Flutter will automatically track which widgets depend on the data and rebuild the parts of your tree that have changed. There is a LocaleQuery widget that is designed to handle locale changes, and you can see how it's used in the Stocks example app.

Briefly, here's what Stocks is doing:

  • Put a callback on root widget (in this case, StocksApp) for handling locale changes. This callback does some work and then returns a customized instance of LocaleQueryData
  • Register this callback as the onLocaleChanged argument to the MaterialApp constructor
  • Child widgets that need locale information use LocaleQuery.of(context).
  • When the locale changes, Flutter only redraws widgets that have dependencies on the locale data.

If you want to track something other than locale changes, you can make your own class that extends InheritedWidget, and include it in the hierarchy near the root of your app. Its parent should be a StatefulWidget with key set to a GlobalKey that accessible to the children. The State of the StatefulWidget should own the data you want to distribute and expose methods for changing it that call setState. If child widgets want change the State's data, they can use the global key to get a pointer to the State (key.currentState) and call methods on it. If they want to read the data, they can call the static of(context) method of your subclass of InheritedWidget and that will tell Flutter that these widgets need to rebuilt whenever your State calls setState.



回答2:

Your Widget should have a setState() method, everytime this method is called, the widget is redrawn.

Documentation : Widget setState()



回答3:

What might work for your use case is using the Navigator to reload the page. I do this when switching between "real" and "demo" mode in my app. Here's an example :

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

You can replace "new SplashPage()" in the above code with whatever main widget (or screen) you would like to reload. This code can be called from anywhere you have access to a BuildContext (which is most places in the UI).



回答4:

I explain how to create a custom 'AppBuilder' widget in this post.

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

You can use the widget by wrapping your MaterialApp with it, for example:

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

You can tell the app to rebuild using:

AppBuilder.of(context).rebuild();


标签: dart flutter