代码之家  ›  专栏  ›  技术社区  ›  Chris

使用shared_preferences在启动时获取主题

  •  0
  • Chris  · 技术社区  · 3 年前

    如何根据存储在中的内容设置应用程序的主题 shared_preferences 如果所有呼叫 shared_preferences 是异步的吗?

    例如,我有一个 ThemeService 从中查找设置主题 shared_preferences 并返回它,这适用于在UI中切换它之类的事情,但我如何在启动时加载它?

    class ThemeService {
    
      static String key = "isDark";
    
      /// Return the ThemeData based on what is persisted.
      Future<ThemeData> getTheme() async {
        final prefs = await SharedPreferences.getInstance();
    
        final isDarkMode = prefs.getBool(key) ?? false;
    
        if (isDarkMode) {
          return ThemeDark().theme;
        } else {
          return ThemeLight().theme;
        }
      }
    
      /// Toggle the theme between light/dark and persist the chosen value.
      Future<void> toggleTheme() async {
        final prefs = await SharedPreferences.getInstance();
    
        final isDarkMode = prefs.getBool(key) ?? false;
    
        if (isDarkMode) {
          Get.changeTheme(ThemeLight().theme);
          await prefs.setBool(key, false);
        } else {
          Get.changeTheme(ThemeDark().theme);
          await prefs.setBool(key, true);
        }
      }
    }
    

    我希望能够这样使用它:

    class App extends StatelessWidget {
    
      final ThemeService themeService = Get.find<ThemeService>();
    
      @override
      Widget build(BuildContext context) {
        return GetMaterialApp(
            debugShowCheckedModeBanner: false,
            initialBinding: InitialBinding(),
            initialRoute: initialRoute(),
            theme: themeService.getTheme(), // Its a future, so can't do this...
            getPages: AppPages.routes);
      }
    }
    
    

    我是新来的,所以我错过了这里的一个概念或模式吗?有没有什么方法可以让我访问不需要的首选项 async/await ?

    0 回复  |  直到 3 年前
        1
  •  0
  •   Chris    3 年前

    正如评论中所建议的,解决方案是包装 GetMaterialApp 在一个 FutureBuilder

      @override
      Widget build(BuildContext context) {
        return FutureBuilder<ThemeData>(
            future: ThemeService().getTheme(),
            builder: (BuildContext context, AsyncSnapshot<ThemeData> snapshot) {
              return GetMaterialApp(
                  debugShowCheckedModeBanner: false,
                  initialBinding: InitialBinding(),
                  initialRoute: initialRoute(),
                  theme: snapshot.data,
                  darkTheme: darkTheme,
                  getPages: AppPages.routes);
            });
      }
    
        2
  •  0
  •   Yayo Arellano    3 年前

    就我个人而言 main 异步。因此,代码将更不像:

    void main() async {
      final themeService = ThemeService();
      final initialTheme = await themeService.getTheme();
      
      runApp(App(initialTheme: initialTheme));
    }
    
    class App extends StatelessWidget {
      
      final ThemeData initialTheme;
    
      const App({Key? key, this.initialTheme}) : super(key: key); 
    
      @override
      Widget build(BuildContext context) {
        return GetMaterialApp(
            debugShowCheckedModeBanner: false,
            initialBinding: InitialBinding(),
            initialRoute: initialRoute(),
            theme: initialTheme, // <-- Now can do it
            getPages: AppPages.routes);
      }
    }