Flutter 检索运行时更改的主题数据问题

Flutter 检索运行时更改的主题数据问题,flutter,asynchronous,dart,Flutter,Asynchronous,Dart,简而言之,我的故事是,我可以成功地动态更改应用程序主题,但在使用最后选择的主题数据启动应用程序时,我失败了 这是主要的。省道: import "./helpers/constants/themeConstant.dart" as themeProfile; class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MultiProvider( providers: [ /

简而言之,我的故事是,我可以成功地动态更改应用程序主题,但在使用最后选择的
主题数据启动应用程序时,我失败了

这是主要的。省道:

import "./helpers/constants/themeConstant.dart" as themeProfile;

class MyApp extends StatelessWidget {
 Widget build(BuildContext context) {
  return MultiProvider(
  providers: [
    //Several ChangeNotifierProviders
  ],
  child: Consumer<AuthenticateProvider>(
    builder: (ctx, authData, _) => ChangeNotifierProvider<ThemeChanger>(
      create: (_) {
        ThemeData themeToBeSet;

        themeProfile.setInitialTheme().then((themeData) {
          themeToBeSet = themeData;
        });

        return ThemeChanger(themeToBeSet);
      },
      child: _MaterialAppWithTheme(authData),
    )
  )
);}}
在这里,我使用
shared\u preferences.dart
包来存储和检索主题数据信息。如果调试此块,我会看到我的
selectedTheme
变量已成功设置为其中一个主题数据。但是,由于某种原因,我无法找到,
main.dart
上的
themetobset
变量未分配给我的
setInitialTheme()
方法的结果

是因为异步吗?但是,Dart不是在用
.then()
等待一个异步方法吗

为了不给我的其他部分留下任何问号,我还分享了Mechanger课程

class ThemeChanger with ChangeNotifier {
 ThemeData _themeData;

 ThemeChanger(
  this._themeData
 );

 getTheme() => _themeData;

 setTheme(ThemeData theme) {
  _themeData = theme;

 notifyListeners();
 }
}
还有,主题材料

class _MaterialAppWithTheme extends StatelessWidget {
  final AuthenticateProvider authData;

  _MaterialAppWithTheme(
    this.authData,
  );

  Widget build(BuildContext context) {
    final theme = Provider.of<ThemeChanger>(context);

    return MaterialApp(
      title: 'Game Shop Demo',
      theme: theme.getTheme(),
      home: authData.isLogedin ?
      HomeScreen(authData.userId) :
      FutureBuilder(
        future: authData.autoLogin(),
        builder: (ctx, authResult) => authResult.connectionState == ConnectionState.waiting ?
        SplashScreen():
        LoginScreen()
      ),
      routes: {
        //Several named routes
      },
    );
  }
}
class\u MaterialAppWithTheme扩展了无状态小部件{
最终身份验证提供者身份验证数据;
_主题材料(
这个.authData,
);
小部件构建(构建上下文){
最终主题=提供者(上下文);
返回材料PP(
标题:“游戏商店演示”,
theme:theme.getTheme(),
主页:authData.isLogedin?
主屏幕(authData.userId):
未来建设者(
future:authData.autoLogin(),
生成器:(ctx,authResult)=>authResult.connectionState==connectionState.waiting?
SplashScreen():
LoginScreen()
),
路线:{
//几个命名路线
},
);
}
}

正如我所怀疑的,我误用了
.then()

当您使用
.then()
时,我以为Dart正在等待,但在遇到这个问题后,我了解到它没有等待

因此,我将
setInitialTheme()
方法带到
ThemeChanger
类中(它以前在另一个类中),并在构造函数中调用它。这里是它的最终版本

class ThemeChanger with ChangeNotifier {
  ThemeData _themeData;

  ThemeChanger() {
    _setInitialTheme();
  }

  getTheme() => _themeData;

  setTheme(ThemeData theme) {
    _themeData = theme;

    notifyListeners();
  }

  Future<ThemeData> _setInitialTheme() async {
    final preferences = await SharedPreferences.getInstance();

    if (!preferences.containsKey(ApplicationConstant.sharedTheme)) {
      _themeData = appThemeDataDark;

      final currentThemeInfo = json.encode({
        "themeStyle": ApplicationConstant.darkAppTheme
      });

      preferences.setString(ApplicationConstant.sharedTheme, currentThemeInfo);

      return _themeData;
    }
    else {
      final extractedThemeInfo = json.decode(preferences.getString(ApplicationConstant.sharedTheme)) as Map<String, dynamic>;
      final chosenTheme = extractedThemeInfo["themeStyle"];

      if (chosenTheme == ApplicationConstant.lightAppTheme) {
        _themeData = appThemeDataLight;

        return _themeData;
      }
      else if (chosenTheme == ApplicationConstant.darkAppTheme) {
        _themeData = appThemeDataDark;

        return _themeData;
      }
      else {
        _themeData = appThemeDataDark; //Its better to define a third theme style, something like appThemeDefault, but in order not to spend more time on dummy stuff, I skip that part

        return _themeData;
      }
    }
  }
}
现在,应用程序正在启动,最后选择的
主题数据
的指针存储在
SharedReferences

class ThemeChanger with ChangeNotifier {
  ThemeData _themeData;

  ThemeChanger() {
    _setInitialTheme();
  }

  getTheme() => _themeData;

  setTheme(ThemeData theme) {
    _themeData = theme;

    notifyListeners();
  }

  Future<ThemeData> _setInitialTheme() async {
    final preferences = await SharedPreferences.getInstance();

    if (!preferences.containsKey(ApplicationConstant.sharedTheme)) {
      _themeData = appThemeDataDark;

      final currentThemeInfo = json.encode({
        "themeStyle": ApplicationConstant.darkAppTheme
      });

      preferences.setString(ApplicationConstant.sharedTheme, currentThemeInfo);

      return _themeData;
    }
    else {
      final extractedThemeInfo = json.decode(preferences.getString(ApplicationConstant.sharedTheme)) as Map<String, dynamic>;
      final chosenTheme = extractedThemeInfo["themeStyle"];

      if (chosenTheme == ApplicationConstant.lightAppTheme) {
        _themeData = appThemeDataLight;

        return _themeData;
      }
      else if (chosenTheme == ApplicationConstant.darkAppTheme) {
        _themeData = appThemeDataDark;

        return _themeData;
      }
      else {
        _themeData = appThemeDataDark; //Its better to define a third theme style, something like appThemeDefault, but in order not to spend more time on dummy stuff, I skip that part

        return _themeData;
      }
    }
  }
}
class MyApp extends StatelessWidget {
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
       //Several ChangeNotifierProviders
      ],
      child: Consumer<AuthenticateProvider>(
        builder: (ctx, authData, _) => ChangeNotifierProvider<ThemeChanger>(
          create: (_) => ThemeChanger(),
          child: _MaterialAppWithTheme(authData),
        )
      )
    );
  }
}