Flutter web app: Load prefs for theme efficiently

Issue

I have a dark/light theme toggle option on my web app. I’m using shared preferences to persist the theme selection. I’m trying to keep the main UI separate from all the theme related work. So I created a loadPrefs() in my theme provider:

loadPrefs() async {
    bool isDark = await ThemePreference().isDark();
    _mode = isDark ? ThemeMode.dark : ThemeMode.light;
    notifyListeners();
  }

The problem is that since this is an async function, I can’t call it in MyApp‘s constructor so I seem forced to call it in the main()

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final app = await Firebase.initializeApp();
  ThemeProvider themeProvider = new ThemeProvider();
  await themeProvider.loadPrefs(); //HERE
  runApp(MyApp(themeProvider: themeProvider));
}

This is really messy because now I have to pass down the theme provider to the widget and then onto the widget’s state class. I feel like there has to be an easier way to do this.

class MyApp extends StatefulWidget {
  final ThemeProvider themeProvider;
  const MyApp({Key? key, required this.themeProvider}) : super(key: key);
  @override
  _MyAppState createState() => _MyAppState(themeProvider: themeProvider);
}

class _MyAppState extends State {
  ThemeProvider themeProvider;
  _MyAppState({required this.themeProvider});
...

Solution

Create your state class as follows

class _MyAppState extends State<MyApp> {

Now you can access all variables in MyApp using widget.themeProvider

If you want to keep your state class dynamic then you must cast your widget as

(widget as MyApp).themeProvider

For better managing your providers you can use

provider package
This package will help you to manage all of your providers easy and effectively
Official talk Listen to this official state management talk

Answered By – Taha Malik

Answer Checked By – Cary Denson (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *