Flutter:如何在Widget启动时读取首选项?

时间:2018-01-16 17:12:41

标签: dart flutter

我一直在尝试在Widget启动时读取首选项,但一直无法找到解决方案。 我希望在TextField中显示用户名(他们可以更改)并将其存储在首选项中,以便在它们返回页面时立即显示。

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController _controller;
  :
  :
  Future<Null> storeName(String name) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString("name", name);
  }

  @override
  initState() async {
    super.initState();
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _controller = new TextEditingController(text: prefs.getString("name"));
  }

  @override
  Widget build(BuildContext context) {
  :
  :
  return new TextField(
               decoration: new InputDecoration(
                 hintText: "Name (optional)",
               ),
               onChanged: (String str) {
                 setState(() {
                   _name = str;
                   storeName(str);
                 });
               },
               controller: _controller,
             )
  }
}

我有了在initState()上使用async的想法:
flutter timing problems on stateful widget after API call
但async似乎在启动时导致此错误:

'package:flutter/src/widgets/framework.dart': Failed assertion: line 967 pos 12: 
'_debugLifecycleState == _StateLifecycle.created': is not true.

我查找了FutureBuilder的示例,但似乎找不到任何类似于我想要做的事情。

4 个答案:

答案 0 :(得分:15)

我建议不要在initState()上使用async。但是你可以通过将SharedPreferences包装在另一个函数中并将其声明为异步来以不同的方式执行此操作。

我修改了你的代码。请检查一下是否有效。非常感谢。

修改后的代码:

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController _controller;
  String _name;

  Future<Null> getSharedPrefs() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _name = prefs.getString("name");
    setState(() {
      _controller = new TextEditingController(text: _name);
    });
  }

  @override
  void initState() {
    super.initState();
    _name = "";
    getSharedPrefs();  
  }

  @override
  Widget build(BuildContext context) {

    return new TextField(
                 decoration: new InputDecoration(
                   hintText: "Name (optional)",
                 ),
                 onChanged: (String str) {
                   setState(() {
                     _name = str;
                     storeName(str);
                 });
               },
               controller: _controller,
    );
  }
}

如果这有帮助,请告诉我。 谢谢。

答案 1 :(得分:1)

initState()是一个同步函数,您无法标记async,因为async将该函数转换为异步函数。

以下代码有助于在加载时加载共享的首选项值,并用于更新小部件。

@override
  void initState() {
    super.initState();
    SharedPreferences.getInstance().then((prefValue) => {
      setState(() {
        _name = prefValue.getString('name')?? "";
        _controller = new TextEditingController(text: _name);
      })
    });
  }

答案 2 :(得分:1)

在应用级别进行。

SharedPreferences prefs;
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  prefs = await SharedPreferences.getInstance();

  // Rest of your code...
}

答案 3 :(得分:0)

还有没有比设置新状态更好的方法了?

我正在构建一个可以在亮和暗模式之间切换的应用,并且该应用在获取用户偏好设置时闪烁...

void _loadOptions() async {
  _options = AppOptions(
    theme: kLightAppTheme,
    textScale: kAllTextScaleValues[0],
    platform: defaultTargetPlatform,
  );

  await _storage.fetchOptions().then((result) {
      if (result != null) {
        setState((){
          _options = result;
        });
      }
    }
  );
}

@override
void initState() {
  super.initState();
  _generateAPIs();
  _loadOptions();
  print(_options.toString());
}