Flutter-仅在读取共享的首选项后如何绘制小部件?

时间:2019-10-07 19:10:44

标签: flutter future

我正在尝试通过创建一个绘制随机路径的应用程序来掌握Flutter(它会在完成之前变得更高级!)。用户可以更改路径中的图块数,并且此值将保存在“共享首选项”中。如果他们不更改切片数,则将其设置为默认值15.5。

我遇到的问题是,它试图在完成读取“共享首选项”之前绘制路径,并且由于未设置图块数量而崩溃。我可以设置默认值,但是它会先绘制默认值,然后使用其他数量的图块重新绘制,这是我不希望的-我希望它首先绘制用户设置的图块数量,并且仅使用如果用户尚未设置号码,则为默认值。

我认为我需要使用FutureBuilder,但是我在网上找不到很多可以帮助到我的地方。这是我到目前为止的内容(这是main.dart):

void main() {
  runApp(MaterialApp(
    title: "Path Maker",
    home: PathMaker(),
  ));
}

class PathMaker extends StatefulWidget {

  int numTiles;

  PathMaker({
        Key key,
        this.numTiles
    }): super(key: key);

  @override
  _PathMakerState createState() => new _PathMakerState();

}

class _PathMakerState extends State<PathMaker> {

  _PathMakerState();

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

    getPreferences();

  }

  @override
  void dispose() {
    super.dispose();
  }

  void getPreferences() async {
      SharedPreferences prefs = await SharedPreferences.getInstance();
      // Get timing variables
      Set<String> keys = prefs.getKeys();
      if(keys.contains('numTiles')) {
        numTiles = prefs.getInt('numTiles');
      }else {
        numTiles = 15.5;
      }
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Path Maker',
      theme: new ThemeData(
        primarySwatch: Colors.green,
      ),
      home: new Path(widget.numTiles),
    );
  }

}

(path.dart是定义Path类的另一个文件-我认为它不相关,但是可以在需要时将其发布)。因此,基本上,我希望它仅在getPreferences完成后才调用build。我该如何处理?我是完全采取了错误的方法吗?

1 个答案:

答案 0 :(得分:1)

使用FutureBuilder使您处在正确的轨道上。

它有两个参数,future期望一些Future,这是一个延迟的计算或一个潜在值。在您的情况下,这是从Future<SharedPreferences>返回的SharedPreferences.getInstance()

然后FutureBuilder会期望一个builder。将使用上下文和与您的未来类型相对应的AsyncSnapshot来调用构建器。 AsyncSnapshot代表与异步计算的最新交互-在您的情况下,是检索共享首选项实例。 AsyncSnapshot.connectionState允许我们根据Future的状态决定要渲染的窗口小部件。 FutureBuilder example详细介绍了不同的状态,现在我们只看ConnectionState.done

done状态下,快照包含一个错误-我们将不在此处处理-或data,即您的异步函数调用的返回值。

以您的示例为例,我们可以创建一个FutureBuilder<SharedPreferences>。通用类型指示将来将返回的类型。我们将共享首选项getInstance方法中的future分配给future参数,并分配一个预期上下文和异步快照的构建器关闭。

使用此代码,您的代码应如下所示:

class _PathMakerState extends State<PathMaker> {
  _PathMakerState();

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

  @override
  void dispose() {
    super.dispose();
  }

  void setTiles(SharedPreferences prefs) {
    // Get timing variables
    Set<String> keys = prefs.getKeys();
    if(keys.contains('numTiles')) {
      widget.numTiles = prefs.getDouble('numTiles');
    }else {
      widget.numTiles = 15.5;
    }
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Path Maker',
      theme: new ThemeData(
        primarySwatch: Colors.green,
      ),
      home: FutureBuilder<SharedPreferences>(
        future: SharedPreferences.getInstance(),
        builder: (BuildContext context, AsyncSnapshot<SharedPreferences> snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.done:
              // get the tile number from the shared preference instance
              // stored in snapshot.data
              setTiles(snapshot.data);
              return Path(widget.numTiles);
            default:
              return Text("Loading...");
          }
        }
      ),
    );
  }

}