dart - Flutter:启动时共享首选项为空

标签 dart sharedpreferences flutter

问题:如果 prefs.getBool('myBool') 返回 null (尽管我的共享首选项值应该已经设置并保存)。但是,当我按下按钮时它确实可以工作(我假设是因为它已经完成了异步代码的运行)。

问题:如何在启动时强制加载共享首选项(所以我的值不是 null)而无需按下打印按钮?

示例代码:

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  MyApp({Key key}) : super(key: key);

  @override
  createState() => new MyAppState();
}

class MyAppState extends State<MyApp> {
  final padding = const EdgeInsets.all(50.0);

  @override
  void initState() {
    super.initState();

    MySharedPreferences.load();
    MySharedPreferences.printMyBool();
  }

  @override
    Widget build(BuildContext context) {
      return new MaterialApp(
        home: new Scaffold(
          body: new Padding(
            padding: padding,
            child: new Column(
              children: <Widget>[
                new Padding(
                  padding: padding,
                  child: new RaisedButton(
                    child: new Text('Save True'),
                    onPressed: () => MySharedPreferences.save(myBool: true),
                  ),
                ),
                new Padding(
                  padding: padding,
                  child: new RaisedButton(
                    child: new Text('Save False'),
                    onPressed: () => MySharedPreferences.save(myBool: false),
                  ),
                ),
                new Padding(
                  padding: padding,
                  child: new RaisedButton(
                    child: new Text('Print myBool'),
                    onPressed: () => MySharedPreferences.printMyBool(),
                ),
              ),
            ],
          ),
        ), 
      ),
    );
  }
}

class MySharedPreferences {
  static bool _myBool;

  static void load() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _myBool = prefs.getBool('myBool') ?? false;
  }

  static void save({myBool: bool}) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _myBool = myBool;
    await prefs.setBool('myBool', _myBool);
  }

  static void printMyBool() {
    print('myBool: ${_myBool.toString()}');
  }
}

结果: 启动时,会打印 myBool: null。按下按钮后,将打印 myBool: false/true

最佳答案

您的问题是您连续调用 load() 和 printMyBool() 。因为 load() 是异步调用它没有执行它的任何代码,它只是调度它。因此,printMyBool 在加载体之前执行。

无需将静态函数放入类中 - 只需将它们声明为顶级函数即可。此外,您并不真的希望 _myBool 是全局的 - 它应该是 Widget 状态的一部分。这样,当您更新它时,Flutter 就知道要重绘树的哪些部分。

我已重组您的代码以删除多余的静态数据。

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() => runApp(new MyApp());

class MyApp extends StatefulWidget {
  MyApp({Key key}) : super(key: key);

  @override
  createState() => new MyAppState();
}

const EdgeInsets pad20 = const EdgeInsets.all(20.0);
const String spKey = 'myBool';

class MyAppState extends State<MyApp> {
  SharedPreferences sharedPreferences;

  bool _testValue;

  @override
  void initState() {
    super.initState();

    SharedPreferences.getInstance().then((SharedPreferences sp) {
      sharedPreferences = sp;
      _testValue = sharedPreferences.getBool(spKey);
      // will be null if never previously saved
      if (_testValue == null) {
        _testValue = false;
        persist(_testValue); // set an initial value
      }
      setState(() {});
    });
  }

  void persist(bool value) {
    setState(() {
      _testValue = value;
    });
    sharedPreferences?.setBool(spKey, value);
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        body: new Center(
          child: new Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              new Padding(
                padding: pad20,
                child: new Text(
                    _testValue == null ? 'not ready' : _testValue.toString()),
              ),
              new Padding(
                padding: pad20,
                child: new RaisedButton(
                  child: new Text('Save True'),
                  onPressed: () => persist(true),
                ),
              ),
              new Padding(
                padding: pad20,
                child: new RaisedButton(
                  child: new Text('Save False'),
                  onPressed: () => persist(false),
                ),
              ),
              new Padding(
                padding: pad20,
                child: new RaisedButton(
                  child: new Text('Print myBool'),
                  onPressed: () => print(_testValue),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

关于dart - Flutter:启动时共享首选项为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49957815/

相关文章:

firebase - Cloud Firestore 不断重新下载文档 - Flutter

flutter 未处理的异常 : FormatException: Invalid date format

dart - Flutter:本地通知插件,当用户点击通知时导航到特定屏幕

flutter - 我的Flutter项目未运行(错误消息)

dart - 文字 flutter 中的倒计时

flutter - 如何在 Flutter 中设置自定义 FontWeight 值

android 共享首选项为空

android - 使用 SharedPreferences 在 ListView 中保存 ToggleButton 状态

arrays - 如何将数组元素int Dart相加

java - 我应该在 onCreate 或 onResume 中从共享首选项加载值吗?