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

标签 flutter future

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

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

我认为我需要使用 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 完成后调用构建。我该如何处理这个问题?我是否完全采取了错误的方法?

最佳答案

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

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

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

done状态快照包含错误(我们不打算在此处处理)或 data ,异步函数调用的返回值。

以您的示例为例,我们可以创建一个 FutureBuilder<SharedPreferences> 。泛型类型表示 future 将返回的类型。我们根据共同的偏好来分配 future getInstance方法到 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...");
          }
        }
      ),
    );
  }

}

关于Flutter - 如何仅在读取共享首选项后才绘制小部件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58275746/

相关文章:

c++ - boost::future 和 Continuations - 值已设置,但 future 仍然受阻

java - 从java中的 future 列表中获得第一个完成 future 的方法是什么?

c++ - 函数返回的 future

flutter - SingleChildScrollView 错误 "RenderFlex children have non-zero flex but incoming height constraints are unbounded"

dart - 使用 BottomNavigationBar 时禁用滑动手势

string - 用 add 0.1 计算 double 给出了点后面的很多数字

flutter - 使用 Flutter 加载屏幕时如何淡入小部件?

dart - 如何为 SliverAppBar 添加抽屉

scala - 没有用于 future 的守护线程的执行上下文

java - 如何继承 CompletableFuture?