BirjuVachhani / adaptive_theme

Easiest way to add support for light and dark theme in your flutter app.
https://pub.dev/packages/adaptive_theme
Apache License 2.0
464 stars 37 forks source link

Theme resetting at app launch #31

Closed timmyrosen closed 2 years ago

timmyrosen commented 2 years ago

UPDATE:

Just tried it on my real android device and there it works perfectly. Not sure why it doesn't work in the simulator.

Describe the bug I have implemented the solution almost identical to the docs, but on a hot restart, the builder method runs twice, where on the first run has the correct theme which is set in the initial prop, but on the second run it's the light theme. On a hot restart I can actually see the colors changing from dark to light in a split second.

Here is the first part of my root build method: I'm using the GetX package, hence the GetMaterialApp method.

@override
  Widget build(BuildContext context) {
    return AdaptiveTheme(
        light: lightTheme,
        dark: darkTheme,
        initial: AdaptiveThemeMode.dark,
        builder: (light, dark) {
          print('light: ${light.scaffoldBackgroundColor}');
          print('dark: ${dark.scaffoldBackgroundColor}');
          return GetMaterialApp(
            navigatorKey: navigatorKey,
            locale: const Locale('sv', 'SE'),
            theme: light,
            darkTheme: dark,

Here is the output from my debug console:

flutter: light: MaterialColor(primary value: Color(0xff4caf50))
flutter: dark: MaterialColor(primary value: Color(0xff4caf50))
[GETX] Instance "GetMaterialController" has been created
[GETX] Instance "GetMaterialController" has been initialized
[GETX] Redirect to null
[GETX] GOING TO ROUTE /home
[GETX] Instance "HomeController" has been created
[GETX] Instance "HomeController" has been initialized
flutter: light: MaterialColor(primary value: Color(0xff673ab7))
flutter: dark: MaterialColor(primary value: Color(0xff673ab7))

As you can see the print in the build method runs twice with different values, where the first values represent the color in the dark mode, and the second time it's the values in the light mode.

Expected behavior I expect the theme set in the initial prop to be the theme in use.

Smartphone (please complete the following information):

BirjuVachhani commented 2 years ago

If you have changed the theme to light at any point then it remembers the choice and persists that across the app lifecycle. You need to retrieve that persisted choice in runApp and pass it as initial value to avoid flashing like that. Because if you don't then it will render UI using that theme meanwhile it is retrieving last changed mode from storage and then applies that mode.

Checkout this section of the docs on how to do that: Get ThemeMode at App Start

If this is not the case for you then do let me know. I'll try to check this out as soon as I can. Thanks.

timmyrosen commented 2 years ago

@BirjuVachhani Okay, I think I understand.

So the first time I run the app with adaptive_theme, the theme set in initial is saved in storage. After that it doesn't matter what I put in initial, because it overrides from storage?

I thought the await AdaptiveTheme.getThemeMode(); code did all of that, but now I see what it does.

Thanks for clarifying, and thanks for a great package!

BirjuVachhani commented 2 years ago

@timmyrosen Yeah, that's why it is called initial so we only use it once.

AdaptiveTheme.getThemeMode(); only retrieves saved state from storage. It is not used automatically as it would require some static state which is not a good idea generally.

Thank you. I'm glad I could help. 🙌🏻