irs*_*han 3 dart flutter flutter-futurebuilder
我在我的一个小部件中使用 FutureBuilder,它需要一个 future。我通过它的构造函数将 future 传递给小部件。问题是,当将 future 传递给小部件时,它会自动执行。由于 FutureBuilder 只接受 Future 而不是 Future Function() 我被迫初始化一个变量,该变量又调用异步函数。但我不知道如何在不执行 Future 的情况下传递它。
这是完整的工作示例:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final icecreamSource = DataService.getIcecream();
final pizzaSource = DataService.getPizza();
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Column(
children: [
MenuButton(label: 'Ice Cream', dataSource: icecreamSource),
MenuButton(label: 'Pizza', dataSource: pizzaSource),
]
),
),
),
);
}
}
class MenuButton extends StatelessWidget {
final String label;
final Future<String> dataSource;
const MenuButton({required this.label, required this.dataSource});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: ElevatedButton(
child: Text(label),
onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (context) => AnotherPage(label: label, dataSource: dataSource)))
),
);
}
}
// Mock service to simulate async data sources
class DataService {
static Future<String> getIcecream() async {
print('Trying to get ice cream...');
return await Future.delayed(const Duration(seconds: 3), () => 'You got Ice Cream!');
}
static Future<String> getPizza() async {
print('Trying to get pizza...');
return await Future.delayed(const Duration(seconds: 2), () => 'Yay! You got Pizza!');
}
}
class AnotherPage extends StatefulWidget {
final String label;
final Future<String> dataSource;
const AnotherPage({required this.label, required this.dataSource});
@override
State<AnotherPage> createState() => _AnotherPageState();
}
class _AnotherPageState extends State<AnotherPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.label)),
body: Center(
child: FutureBuilder<String>(
future: widget.dataSource,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if(snapshot.hasData) {
return Text('${snapshot.data}');
} else if(snapshot.hasError) {
return Text('Error occurred ${snapshot.error}');
} else {
return Text('Fetching ${widget.label}, please wait...');
}
}
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
预期的行为是,当我按下主页上的“冰淇淋”或“披萨”按钮时,应出现名为“另一页”的小部件/屏幕,并且应执行异步请求,在此期间应显示加载消息。然而,正在发生的情况是,在加载主页时,甚至在按下任何按钮之前,两个异步请求都会被执行。按下任何按钮时,不会出现加载消息,因为请求已经完成,因此它直接显示结果,这是完全不希望的。我现在对 Futures 和 Future Functions 完全感到困惑。有人请帮帮我。
Future您可以传递返回 的函数本身,而不是传递Future。您可以在DartPad上尝试这个示例。
你必须MyApp这样修改:
final icecreamSource = DataService.getIcecream; // No () as we want to store the function
final pizzaSource = DataService.getPizza; // Here aswell
Run Code Online (Sandbox Code Playgroud)
MenuButton我们需要AnotherPage:
final Future<String> Function() dataSource; // Instead of Future<String> dataSource
Run Code Online (Sandbox Code Playgroud)
不,我们可以将 future 直接传递给,FutureBuilder但让 FutureBuilder 直接执行 future 是不好的做法,因为构建方法被多次调用。相反,我们有这个:
class _AnotherPageState extends State<AnotherPage> {
late final Future<String> dataSource = widget.dataSource(); // Gets executed right here
...
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以把这个未来交给未来的建造者。