【问题标题】:Flutter/Dart : How to wait for asynchronous task before app starts?Flutter/Dart:如何在应用启动前等待异步任务?
【发布时间】:2020-12-04 10:00:36
【问题描述】:

我正在开发一个 dart 应用程序,我想在其中获取缓存中存在的数据 (SharedPreferences),然后将其显示在应用程序的 UI(主屏幕)上。

问题:由于 SharedPreferences 是一个等待调用,我的主页加载,尝试读取数据并且应用程序崩溃,因为尚未从 SharedPreferences 获取数据,并且在此之前应用程序加载。

在从 SharedPreferences 读取缓存完成之前,如何才能启动应用程序? 这是必需的,因为我必须在应用程序的主页上显示来自 SharedPreferences 的数据。 我的项目的各种视图文件调用静态函数: MyService.getValue(key) 由于 cacheResponseJson 尚未填充而崩溃。我想在我的应用启动之前等待 SharedPreferences 完成。

Class MyService {
    String _cacheString;
    static Map < String, dynamic > cacheResponseJson;
    MyService() {
        asyncInit();
    }

    Future < void > asyncInit() async {
        SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
        _cacheString = sharedPreferences.getString(“ConfigCache”);
        cacheResponseJson = jsonDecode(ecsCacheString);
    }

    static String getValue(String key) {
        return cacheResponseJson[key];
    }
}

void main() {
    MyService s = MyService();
}

任何帮助将不胜感激!

【问题讨论】:

    标签: flutter asynchronous dart caching sharedpreferences


    【解决方案1】:

    您可以在main() 方法中运行代码,然后调用runApp() 来启动您的应用程序。

    例如:

    void main() async {
        WidgetsFlutterBinding.ensureInitialized();  // makes sure plugins are initialized
        final sharedPreferences = MySharedPreferencesService();  // however you create your service
        final config = await sharedPreferences.get('config');
        runApp(MyApp(config: config));
    }
    

    【讨论】:

    • 这就是我所做的。我不知道做主异步是否是一个好习惯,但它还没有崩溃。 :-)
    • Dart 程序首先找到一个名为main() 的函数并执行它,然后运行直到所有异步工作完成。 main() 是否有 async 关键字无关紧要,例如,您可以写:void main() {_main();} where _main() is is async,行为将是相同的。简而言之,让你的主要方法async完全没问题。
    • WidgetsFlutterBinding.ensureInitialized()重要
    【解决方案2】:

    你可以尝试包装函数asyncInit() in initstate然后在函数中然后setstate

    _cacheString = sharedPreferences.getString(“ConfigCache”);
    cacheResponseJson = jsonDecode(ecsCacheString);
    

    我希望它有效。

    【讨论】:

      【解决方案3】:

      避免在runApp()函数之外使用初始化等,你可以创建一个单例

      class MyService{
        MyService._oneTime();
      
        static final _instance = MyService._oneTime();
      
        factory MyService(){
          return _instance;
        }
      
        Future <bool> asyncInit() async {
          //do stuff
          return true;
        }
      }
      

      并像这样将其合并到 UI 中

      runApp(
        FutureBuilder(
          future: MyService().asyncInit(),
          builder: (_,snap){
            if(snap.hasData){
              //here you can use the MyService singleton and its members
              return MaterialApp();
            }
            return CircularProgressIndicator();
          },
        )
      );
      

      如果您采用这种方法,您可以在数据加载时为用户提供任何与 UI 相关的反馈

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-20
        • 2019-06-28
        • 2021-09-27
        • 1970-01-01
        • 2014-09-06
        • 1970-01-01
        • 2017-12-11
        • 2021-03-15
        相关资源
        最近更新 更多