我试图通过创建一个绘制随机路径的应用程序来掌握 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/