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

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();

I should note this is probably a bit of an anti-pattern in Flutter. In our app I’ve found it extremely useful as it compliments our Redux architecture. I plan to discuss this in greater detail in the next post…

flutter-logo-sharing

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 Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s