![](/img/trans.png)
[英]Flutter: How to pass array data from json Future< to Widget
[英]Flutter - How to pass a future to a widget without executing it?
我在我的一個小部件中使用 FutureBuilder,它需要一個未來。 我通過它的構造函數將未來傳遞給小部件。 問題在於,在將未來傳遞給小部件時,它會自動執行。 由於 FutureBuilder 只接受 Future 而不是 Future Function() 我被迫初始化一個變量,該變量又調用異步 function。 但我不知道如何在沒有被執行的情況下通過未來。
這是完整的工作示例:
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...');
}
}
),
),
);
}
}
預期的行為是,當我按下主頁上的“冰淇淋”或“披薩”按鈕時,應該出現名為“另一個頁面”的小部件/屏幕,並且應該執行異步請求,在此期間應該顯示加載消息。 然而,正在發生的事情是在加載主頁時,甚至在按下任何按鈕之前,兩個異步請求都被執行。 在按下任何按鈕時,加載消息不會出現,因為請求已經完成,因此它直接顯示結果,這是完全不可取的。 我現在對 Futures 和 Future Functions 完全感到困惑。 有人請幫幫我。
而是通過 Future function,你為什么不嘗試傳遞一個字符串?
移除所有final Future<String> dataSource;
. 你不需要它。
您只能使用label
。
.....
body: Center(
child: FutureBuilder<String>(
future: widget.label == 'Pizza'
? DataService.getPizza()
: DataService.getIcecream(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
....
我只是在https://dartpad.dev中測試它。 它的工作正常。 如果您可以通過簡單的方式實現,則不必復雜化。
而不是傳遞Future
您可以傳遞 function 本身,它返回Future
。 你可以在DartPad上試試這個例子。
您必須像這樣修改MyApp
:
final icecreamSource = DataService.getIcecream; // No () as we want to store the function
final pizzaSource = DataService.getPizza; // Here aswell
在MenuButton
和AnotherPage
中,我們需要:
final Future<String> Function() dataSource; // Instead of Future<String> dataSource
不,我們可以將未來直接傳遞給FutureBuilder
,但是讓 FutureBuilder 直接執行未來是不好的做法,因為構建方法被多次調用。 相反,我們有這個:
class _AnotherPageState extends State<AnotherPage> {
late final Future<String> dataSource = widget.dataSource(); // Gets executed right here
...
}
現在我們可以將這個未來傳遞給未來的構建者。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.