简体   繁体   English

使用Flutter和Dart,这是实现这一未来的最好方法吗?

[英]Using Flutter and Dart, is this the best way to achieve this Future?

I know that there are other ways of achieving this, but I want to use a Future via initState() to obtain a List using SharedPreferences without using await. 我知道还有其他方法可以实现此目的,但是我想通过initState()使用Future来使用SharedPreferences获得List而不使用await。 The following illustrates what I want to achieve, and it does work. 以下内容说明了我要实现的目标,并且确实有效。 Because I have never used this pattern previously, I'm just unsure if it's the best way (without using await). 因为我以前从未使用过这种模式,所以我不确定这是否是最好的方法(不使用await)。 Is there a better way without using 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();
}


What you did is fine in terms of asynchrony. 就异步而言,您所做的工作很好。 However, it's too verbose. 但是,它太冗长了。 For example, you do not need to transfer the prefs instance through state. 例如,您不需要通过状态传输prefs实例。

Another improvement could be to check whether the widget is still mounted when the Future is done. 另一个改进可能是检查Future完成后是否仍挂载了窗口小部件。 (If you use a FutureBuilder , you don't need to worry about this.) (如果使用FutureBuilder ,则不必为此担心。)

A problem with your code is that you're setting state variables outside setState() . 您的代码有一个问题,就是您要在setState()之外设置状态变量。 It is not guaranteed to work well that way, I swear I had old state used sometimes when I did that. 不能保证那样做得很好,我发誓我有时会使用旧状态。 You should set them within setState() 您应该在setState()设置它们

Here are a couple of different ways I would prefer to code it: 以下是几种我希望对其进行编码的方式:

  @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");
      }
    });
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM