Flutter: How to rebuild the entire app to change the theme or locale

Update: although this widget does work as described it’s an anti-pattern. The better approach would be to define the state and let Flutter handle it. Thanks to Pascal Welsch for pointing this out and Iiro Krankka for providing a working example.

Settings which are defined in the MaterialApp widget, such as the theme or locale, require the entire widget tree to be rebuilt when changed.

This article (and package) by Norbert Kozsir make it easy to set the app’s theme however in our case we need to manage additional top level properties including the locale. All of the settings are stored in our central data store, we just need to tell the app to rebuild after the settings are changed.

This AppBuilder widget (which is a stripped down version of Norbert’s solution) makes it possible for any part of the widget tree to request the app to be rebuilt. I believe the key aspect which makes it work is that the build method calls a builder function rather than directly returning a child widget.

import 'package:flutter/material.dart';

class AppBuilder extends StatefulWidget {
  final Function(BuildContext) builder;

  const AppBuilder(
      {Key key, this.builder})
      : super(key: key);

  @override
  AppBuilderState createState() => new AppBuilderState();

  static AppBuilderState of(BuildContext context) {
    return context.ancestorStateOfType(const TypeMatcher<AppBuilderState>());
  }
}

class AppBuilderState extends State<AppBuilder> {

  @override
  Widget build(BuildContext context) {
    return widget.builder(context);
  }

  void rebuild() {
    setState(() {});
  }
}

You can use this class by wrapping your MaterialApp with it, for example:

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

Finally, you can tell the app to rebuild using:

AppBuilder.of(context).rebuild();

You can see a full working example here.

download

5 thoughts on “Flutter: How to rebuild the entire app to change the theme or locale”

  1. What if I want to redraw widget in Page1 after I pressed back button from Page2? Let say in Page1, I have text widget with value ‘ABCD’, then I go into Page2 using route pushNamed. While in Page2, I have textfield widget, and put ‘WXYZ’ and save its value. Then I pressed back button (back to Page1), and I want to replace ‘ABCD’ with those ‘WXYZ’ value.

Leave a comment