使用Flutter和Dart,这是实现这个未来的最佳方式吗?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (25)

我知道还有其他方法可以实现这一点,但我希望通过initState()使用Future来使用SharedPreferences获取List而不使用await。以下说明了我想要实现的目标,并且确实有效。因为我之前从未使用过这种模式,所以我只是不确定它是否是最好的方式(不使用等待)。没有使用等待有更好的方法吗?

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

class _MyHomePageState extends State<MyHomePage> {
  SharedPreferences _prefs;
  String _sMessage1;
  String _sMessage2;
  List<String> _lsCategories;

  @override
  void initState() {
    super.initState();
    Future<void> future = _initPreferences();
    future.then((_) {
      if (_prefs != null) {
        try {
          _lsCategories = _prefs.getStringList("categories") ?? [];
          debugPrint("Categories = $_lsCategories");
          _sMessage2 = "Categories loaded OK";
        } catch (vError) {
          _sMessage2 = ("Error loading categories = $vError");
        }
      }
      setState(() {});
    });
  }

  Future<void> _initPreferences() {
    return SharedPreferences.getInstance().then((prefs) {
      _prefs = prefs;
      _sMessage1 = "Preferences initialized OK";
    }).catchError((vError) {
      _sMessage1 = "Error initializing preferences = ${vError.toString()}";
      _sMessage2 = "Unable to load categories";
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _createText(_sMessage1),
            SizedBox(height: 20),
            _createText(_sMessage2),
          ],
        ),
      ),
    );
  }
}

Text _createText(String sText) {
  return Text(sText == null ? "" : sText,
      style: TextStyle(
          color: Colors.red[500], fontWeight: FontWeight.bold, fontSize: 20));
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Future Test',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: "Flutter Future Test"),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}


提问于
用户回答回答于

你在异步方面做得很好。但是,它太冗长了。例如,您不需要通过状态传输prefs实例。

另一项改进可能是在完成后检查窗口小部件是否仍然挂载Future。(如果你使用a FutureBuilder,你不必担心这个。)

您的代码存在的问题是您在外部设置状态变量setState()。我不能保证这种方式运作良好,我发誓当我这样做的时候我曾经使用旧状态。你应该在里面设置它们setState()

以下是我希望编写代码的几种不同方法:

  @override
  void initState() {
    super.initState();
    SharedPreferences.getInstance().then((prefs) {
      if(!mounted) return;
      setState(() {
        _prefs = prefs;
        _lsCategories = _prefs.getStringList("categories") ?? [];
        debugPrint("Categories = $_lsCategories");
        _sMessage2 = "Categories loaded OK";
      });
    }).catchError((vError) {
      setState(() {
        _sMessage2 = ("Error loading categories = $vError");
      });
    });
  }
  @override
  void initState() {
    super.initState();
    _initPreferences();
  }

  Future<void> _initPreferences() async {
    final prefs = await SharedPreferences.getInstance();
    if (!mounted) return;
    setState(() {
      try {
        _prefs = prefs;
        _lsCategories = _prefs.getStringList("categories") ?? [];
        debugPrint("Categories = $_lsCategories");
        _sMessage2 = "Categories loaded OK";
      } catch (vError) {
        _sMessage2 = ("Error loading categories = $vError");
      }
    });
  }

扫码关注云+社区

领取腾讯云代金券